Skip to content

Commit b6c56a6

Browse files
add:translate the blog (apache#867)
1 parent aece0c5 commit b6c56a6

28 files changed

+9114
-5
lines changed

i18n/en/docusaurus-plugin-content-blog/integrate-seata-with-spring-cloud.md

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,246 @@ author: dafei.Fei
44
date: 2019/04/15
55
keywords: [fescar, seata, distributed transaction]
66
---
7+
8+
# 1. Introduction
9+
Many developers are already familiar with Fescar. However, Fescar has now transformed into Seata. If you're not aware of Seata, please check the following link.
10+
11+
SEATA GITHUB: [https://github.com/apache/incubator-seata]
12+
13+
We extend our sincere thanks and greetings to the Alibaba team for their contributions in bringing numerous open-source software to developers.
14+
15+
Today, I will share my insights on integrating Seata with Spring Cloud, aiming to help more developers avoid common pitfalls and streamline their setup process.
16+
17+
# 2. Project Overview
18+
19+
The setup process is as follows: client -> gateway -> service consumer -> service provider.
20+
21+
```
22+
Technical Framework: spring cloud gateway
23+
spring cloud fegin
24+
nacos1.0.RC2
25+
fescar-server0.4.1 (Seata)
26+
```
27+
28+
For instructions on starting Nacos, please refer to: [Nacos Startup Guide](https://nacos.io/zh-cn/docs/quick-start.html)
29+
30+
Seata supports various service registration methods. In the `fescar-server-0.4.1\conf` directory, you will find:
31+
32+
```
33+
file.conf
34+
logback.xml
35+
nacos-config.sh
36+
nacos-config.text
37+
registry.conf
38+
```
39+
40+
There are a total of five files. Among them, `file.conf` and `registry.conf` are needed in the code segments for both service consumers and providers. Note: `file.conf` and `registry.conf` must be included in the current applications in use, i.e., both service consumer and provider applications must include them. If you are using a configuration center like Nacos or ZK, `file.cnf` can be ignored. However, if `type="file"` is specified, then `file.cnf` must be used.
41+
42+
Below is the configuration information in the `registry.conf` file. The `registry` section is for the service registration center configuration, and the `config` section is for the configuration center.
43+
44+
As shown below, Seata currently supports nacos, file, eureka, redis, zookeeper, etc., for registration and configuration. The default downloaded configuration type is `file`. The choice of method depends on your project’s actual requirements. Here, I chose nacos, but eureka can also be used. Both versions have been tested and work fine.
45+
46+
Note: If you are integrating with eureka, please use the latest official version.
47+
48+
# 3. Core Configuration
49+
50+
```java
51+
registry {
52+
# file, nacos, eureka, redis, zk
53+
type = "nacos"
54+
55+
nacos {
56+
serverAddr = "localhost"
57+
namespace = "public"
58+
cluster = "default"
59+
}
60+
eureka {
61+
serviceUrl = "http://localhost:1001/eureka"
62+
application = "default"
63+
weight = "1"
64+
}
65+
redis {
66+
serverAddr = "localhost:6379"
67+
db = "0"
68+
}
69+
zk {
70+
cluster = "default"
71+
serverAddr = "127.0.0.1:2181"
72+
session.timeout = 6000
73+
connect.timeout = 2000
74+
}
75+
file {
76+
name = "file.conf"
77+
}
78+
}
79+
80+
config {
81+
# file, nacos, apollo, zk
82+
type = "nacos"
83+
84+
nacos {
85+
serverAddr = "localhost"
86+
namespace = "public"
87+
cluster = "default"
88+
}
89+
apollo {
90+
app.id = "fescar-server"
91+
apollo.meta = "http://192.168.1.204:8801"
92+
}
93+
zk {
94+
serverAddr = "127.0.0.1:2181"
95+
session.timeout = 6000
96+
connect.timeout = 2000
97+
}
98+
file {
99+
name = "file.conf"
100+
}
101+
}
102+
```
103+
104+
Note that `nacos-config.sh` is a script that needs to be executed if using Nacos as the configuration center. It initializes some default settings for Nacos.
105+
106+
Refer to the official guide for SEATA startup: Note that the official startup command separates parameters with spaces, so be careful. The IP is an optional parameter. Due to DNS resolution, sometimes when registering with Nacos, Fescar might obtain the address using the computer name, requiring you to specify the IP or configure the host to point to the IP. This issue has been fixed in the latest SEATA version.
107+
108+
```shell
109+
sh fescar-server.sh 8091 /home/admin/fescar/data/ IP (optional)
110+
```
111+
112+
As mentioned earlier, `file.conf` and `registry.conf` are needed in our code. The focus here is on `file.conf`. It is only loaded if `registry` is configured with `file`. If using ZK, Nacos, or other configuration centers, it can be ignored. However, `service.localRgroup.grouplist` and `service.vgroupMapping` need to be specified in the configuration center so that your client can automatically obtain the corresponding SEATA service and address from the configuration center upon startup. Failure to configure this will result in an error due to the inability to connect to the server. If using eureka, the config section should specify `type="file"`. SEATA config currently does not support eureka.
113+
114+
```java
115+
transport {
116+
# tcp, udt, unix-domain-socket
117+
type = "TCP"
118+
# NIO, NATIVE
119+
server = "NIO"
120+
# enable heartbeat
121+
heartbeat = true
122+
# thread factory for netty
123+
thread-factory {
124+
boss-thread-prefix = "NettyBoss"
125+
worker-thread-prefix = "NettyServerNIOWorker"
126+
server-executor-thread-prefix = "NettyServerBizHandler"
127+
share-boss-worker = false
128+
client-selector-thread-prefix = "NettyClientSelector"
129+
client-selector-thread-size = 1
130+
client-worker-thread-prefix = "NettyClientWorkerThread"
131+
# netty boss thread size, will not be used for UDT
132+
boss-thread-size = 1
133+
# auto default pin or 8
134+
worker-thread-size = 8
135+
}
136+
}
137+
service {
138+
# vgroup -> rgroup
139+
vgroup_mapping.service-provider-fescar-service-group = "default"
140+
# only support single node
141+
localRgroup.grouplist = "127.0.0.1:8091"
142+
# degrade current not support
143+
enableDegrade = false
144+
# disable
145+
disable = false
146+
}
147+
148+
client {
149+
async.commit.buffer.limit = 10000
150+
lock {
151+
retry.internal = 10
152+
retry.times = 30
153+
}
154+
}
155+
```
156+
157+
# 4. Service Details
158+
Two key points need attention:
159+
160+
```java
161+
grouplist IP: This is the IP and port of the current Fescar server.
162+
vgroup_mapping configuration.
163+
```
164+
165+
`vgroup_mapping.service-provider-fescar-service-group`: The service name here is actually the application name configured in the `application.properties` of your consumer or provider, e.g., `spring.application.name=service-provider`. In the source code, the application name is concatenated with `fescar-service-group` to form the key. Similarly, the value is the name of the current Fescar service. `cluster = "default" / application = "default"`
166+
167+
```java
168+
vgroup_mapping.service-provider-fescar-service-group = "default"
169+
# only support single node
170+
localRgroup.grouplist = "127.0.0.1:8091"
171+
```
172+
173+
Both provider and consumer need to configure these two files.
174+
175+
If you use Nacos as the configuration center, you need to add the configuration in Nacos by adding the configuration manually.
176+
177+
# 5. Transaction Usage
178+
In my code, the request is load-balanced through the gateway to the consumer. The consumer then requests the provider through Feign. The official example uses Feign, but here, the request is forwarded directly through the gateway, so the global transaction is handled in the controller layer, similar to the official demo.
179+
180+
```java
181+
@RestController
182+
public class DemoController {
183+
@Autowired
184+
private DemoFeignClient demoFeignClient;
185+
186+
@Autowired
187+
private DemoFeignClient2 demoFeignClient2;
188+
@GlobalTransactional(timeoutMills = 300000, name = "spring-cloud-demo-tx")
189+
@GetMapping("/getdemo")
190+
public String demo() {
191+
192+
// Call service A and simply save
193+
ResponseData<Integer> result = demoFeignClient.insertService("test", 1);
194+
if(result.getStatus() == 400) {
195+
System.out.println(result + "+++++++++++++++++++++++++++++++++++++++");
196+
throw new RuntimeException("this is error1");
197+
}
198+
199+
// Call service B and test rollback of service A upon error
200+
ResponseData<Integer> result2 = demoFeignClient2.saveService();
201+
202+
if(result2.getStatus() == 400) {
203+
System.out.println(result2 + "+++++++++++++++++++++++++++++++++++++++");
204+
throw new RuntimeException("this is error2");
205+
}
206+
207+
return "SUCCESS";
208+
}
209+
}
210+
```
211+
212+
This concludes the core integration of transactions. Here, service A and B are both providers. When service B encounters an error, the global transaction rolls back. Each transaction can handle its local transactions independently.
213+
214+
SEATA uses a global XID to uniformly identify transactions. I will not list the database tables needed for SEATA here. For details, refer to: [spring-cloud-fescar official DEMO](https://github.com/spring-cloud-incubator/spring-cloud-alibaba/tree/master/spring-cloud-alibaba-examples/fescar-example)
215+
216+
# 5.Data Proxy
217+
218+
Another important point is that in a distributed database service, each database needs an `undo_log` table to handle XID storage.
219+
220+
Additionally, each service project needs a database connection pool proxy. Currently, only Druid connection pool is supported. More will be supported in the future.
221+
222+
```java
223+
@Configuration
224+
public class DatabaseConfiguration {
225+
226+
@Bean(destroyMethod = "close", initMethod = "init")
227+
@ConfigurationProperties(prefix="spring.datasource")
228+
public DruidDataSource druidDataSource() {
229+
return new DruidDataSource();
230+
}
231+
232+
@Bean
233+
public DataSourceProxy dataSourceProxy(DruidDataSource druidDataSource) {
234+
return new DataSourceProxy(druidDataSource);
235+
}
236+
237+
@Bean
238+
public SqlSessionFactory sqlSessionFactory(DataSourceProxy dataSourceProxy) throws Exception {
239+
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
240+
factoryBean.setDataSource(dataSourceProxy);
241+
return factoryBean.getObject();
242+
}
243+
}
244+
```
245+
246+
Pay attention to the configuration file and data proxy. Without a data source proxy, `undo_log` will have no data, making XID management impossible.
247+
248+
Author: Da Fei
249+

0 commit comments

Comments
 (0)