一、nacos安装
详情参看:https://blog.youkuaiyun.com/cts529269539/article/details/105839593
二、seata安装
环境:window X64 mysql8.0 python3.x
1、seata配置
本人使用的1.2.0,下载完成后解压为seata文件夹,打开conf文件夹,修改registry.conf里面的type为nacos
下载包里面没有config.txt和nacos-config.py,需要去官网下载:https://github.com/seata/seata/blob/1.2.0/script/config-center/config.txt
本人的config.txt:
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableClientBatchSendRequest=false
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.bossThreadSize=1
transport.threadFactory.workerThreadSize=default
transport.shutdown.wait=3
service.vgroupMapping.user-service-group=default
service.default.grouplist=127.0.0.1:8091
service.enableDegrade=false
service.disableGlobalTransaction=false
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=false
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
store.mode=file
store.file.dir=file_store/data
store.file.maxBranchSessionSize=16384
store.file.maxGlobalSessionSize=512
store.file.fileWriteBufferCacheSize=16384
store.file.flushDiskMode=async
store.file.sessionReloadReadSize=100
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Hongkong
store.db.user=root
store.db.password=root
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=undo_log
client.log.exceptionRate=100
transport.serialization=seata
transport.compressor=none
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
重点修改的地方为:service.vgroupMapping.user-service-group=default
注:vgroupMapping为1.2新的名字,1.1以前为vgroup_mapping
xxx-group中的xxx为项目中配置的spring-application-name的名字;
已db形式启动需要修改 store.db中的信息,需要创建表,官方脚本:
https://github.com/seata/seata/blob/1.2.0/script/server/db/mysql.sql
增加undo_log
CREATE TABLE `undo_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int(11) NOT NULL,
`log_created` datetime NOT NULL,
`log_modified` datetime NOT NULL,
`ext` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
2、将配置信息导入nacos
下载完nacos-config.py,执行此脚本需要安装Python,下载地址:https://www.python.org/,本人使用3.x版本
在conf目录下执行 下面命令
nacos-config.py 127.0.0.1:8848
出现这些日志,说明我们已经将seata配置加载到了nacos了
XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXX
metrics.exporterPrometheusPort=9898
init nacos config finished, please start seata-server.
3、运行seata
修改conf下的logback.xml,中的
###<property name="LOG_HOME" value="${user.home}/logs/seata"/>
###修改为自己的安装地址
<property name="LOG_HOME" value="E:/logs/seata"/>
执行
seata-server.bat -p 8091 -h 127.0.0.1 -m db -n 1
脚本参数:
- -p
指定启动
seata server
的端口号。 - -h
指定
seata server
所绑定的主机
,这里配置要注意指定的主机IP要与业务服务内的配置文件保持一致,如:-h 192.168.1.10
,业务服务配置文件内应该配置192.168.1.10
,即使在同一台主机上也要保持一致。 - -m
事务日志、事务执行信息存储的方式,目前支持
file
(文件方式)、db
(数据库方式,建表语句请查看config/db_store.sql
、config/db_undo_log.sql
)
启动成功
二、项目准备
创建2个springboot项目,一个为user-service ,一个为order-service
1、user-service
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-seata-test</artifactId>
<groupId>spring-cloud-seata-test</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-seata-user</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- nacos -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.2.1.RELEASE</version>
</dependency>
<!-- seata-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-seata</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>1.1.0</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
resouce目录下:
application.yml
# 数据源配置
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
password: root
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: root
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
alibaba:
seata:
tx-service-group: user-service-group
server:
port: 8085
mybatis:
mapper-locations: classpath:mybatis/*.xml
type-aliases-package: com.cts.user
#showSql
logging:
level:
com:
example:
mapper : debug
nacos:
config:
server-addr: 127.0.0.1:8848
registry.conf是seata安装目前conf下的文件,需要copy到resource下
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
nacos {
application = "serverAddr"
serverAddr = "127.0.0.1:8848"
namespace = ""
username = ""
password = ""
}
eureka {
serviceUrl = "http://localhost:8761/eureka"
weight = "1"
}
redis {
serverAddr = "localhost:6379"
db = "0"
password = ""
timeout = "0"
}
zk {
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
username = ""
password = ""
}
consul {
serverAddr = "127.0.0.1:8500"
}
etcd3 {
serverAddr = "http://localhost:2379"
}
sofa {
serverAddr = "127.0.0.1:9603"
region = "DEFAULT_ZONE"
datacenter = "DefaultDataCenter"
group = "SEATA_GROUP"
addressWaitTime = "3000"
}
file {
name = "file.conf"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3、springCloudConfig
type = "nacos"
nacos {
serverAddr = "127.0.0.1:8848"
namespace = ""
group = "SEATA_GROUP"
username = ""
password = ""
}
consul {
serverAddr = "127.0.0.1:8500"
}
apollo {
appId = "seata-server"
apolloMeta = "http://192.168.1.204:8801"
namespace = "application"
}
zk {
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
username = ""
password = ""
}
etcd3 {
serverAddr = "http://localhost:2379"
}
file {
name = "file.conf"
}
}
UserService主要代码如下,通过2中方式调用order-service,feign和restTemplate
@Service
public class UserService {
Log log = LogFactory.getLog(UserService.class);
@Autowired
UserDao userDao;
@Autowired
OrderFeignClient orderFeignClient;
@Autowired
RestTemplate restTemplate;
@GlobalTransactional(timeoutMills = 2000,name = "用户")
@Transactional(rollbackFor = Exception.class)
public void insert(){
log.info("开始全局事物,XID="+ RootContext.getXID());
UserDto userDto = new UserDto();
userDto.setMobile("13811210013");
userDto.setName("zhangsan1");
userDto.setPassword("#$%@!#!@#");
userDto.setId(100);
try{
userDao.insert(userDto);
}catch (Exception e){
throw e;
}
try{
orderFeignClient.add(userDto.getName());
// restTemplate.getForObject("http://127.0.0.1:8086/order/add?name="+userDto.getName(), String.class);
}catch (Exception e){
throw e;
}
}
}
OrderFeignClient
@FeignClient(name = "order-service")
public interface OrderFeignClient {
@GetMapping("order/add")
void add(@RequestParam("name") String name);
}
2、order-service
OrderController
@RestController
@RequestMapping("order")
public class OrderController {
@Autowired
OrderService orderService;
@RequestMapping(value = "/add",method = RequestMethod.GET)
public String insert(String name){
orderService.insert(name);
return "success";
}
}
OrderService
@Service
public class OrderService {
@Autowired
private OrderDao orderDao;
@Transactional(rollbackFor = Exception.class)
public void insert(String name){
OrderDto orderDto = new OrderDto();
orderDto.setOrderNo(name+ UUID.randomUUID().toString());
orderDto.setAmount(BigDecimal.TEN);
orderDto.setId(100);
orderDao.insert(orderDto);
}
}
如果order插入失败,user中的add操作就不会成功;
详细代码:https://gitee.com/ctslyw/spring-demo/tree/master/spring-cloud-seata-test