分布式事务 SEATA-1.4.1 AT模式 配合NACOS 应用
SEATA 配置
使用 nacos 做为配置中心配置 SEATA
当前 SEATA 版本: 1.4.1
TC (Transaction Coordinator) - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。
配置参数
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.app-server-tx-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
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
store.mode=db
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.jdbc.Driver
store.db.url=url
store.db.user=root
store.db.password=123456
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
store.redis.host=127.0.0.1
store.redis.port=6379
store.redis.maxConn=10
store.redis.minConn=1
store.redis.database=10
store.redis.password=null
store.redis.queryLimit=100
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
nacos bash 脚本
nacos-config.sh
while getopts ":h:p:g:t:u:w:" opt
do
case $opt in
h)
host=$OPTARG
;;
p)
port=$OPTARG
;;
g)
group=$OPTARG
;;
t)
tenant=$OPTARG
;;
u)
username=$OPTARG
;;
w)
password=$OPTARG
;;
?)
echo " USAGE OPTION: $0 [-h host] [-p port] [-g group] [-t tenant] [-u username] [-w password] "
exit 1
;;
esac
done
if [[ -z ${host} ]]; then
host=localhost
fi
if [[ -z ${port} ]]; then
port=8848
fi
if [[ -z ${group} ]]; then
group="SEATA_GROUP"
fi
if [[ -z ${tenant} ]]; then
tenant=""
fi
if [[ -z ${username} ]]; then
username=""
fi
if [[ -z ${password} ]]; then
password=""
fi
nacosAddr=$host:$port
contentType="content-type:application/json;charset=UTF-8"
echo "set nacosAddr=$nacosAddr"
echo "set group=$group"
failCount=0
tempLog=$(mktemp -u)
function addConfig() {
curl -X POST -H "${contentType}" "http://$nacosAddr/nacos/v1/cs/configs?dataId=$1&group=$group&content=$2&tenant=$tenant&username=$username&password=$password" >"${tempLog}" 2>/dev/null
if [[ -z $(cat "${tempLog}") ]]; then
echo " Please check the cluster status. "
exit 1
fi
if [[ $(cat "${tempLog}") =~ "true" ]]; then
echo "Set $1=$2 successfully "
else
echo "Set $1=$2 failure "
(( failCount++ ))
fi
}
count=0
for line in $(cat config.txt | sed s/[[:space:]]//g); do
(( count++ ))
key=${line%%=*}
value=${line#*=}
addConfig "${key}" "${value}"
done
echo "========================================================================="
echo " Complete initialization parameters, total-count:$count , failure-count:$failCount "
echo "========================================================================="
if [[ ${failCount} -eq 0 ]]; then
echo " Init nacos config finished, please start seata-server. "
else
echo " init nacos config fail. "
fi
同步 config 配置到 nacos
进入 TC 服务器
新建文件夹 seata-config
进入 seata-config
新建 config.txt 文件并复制配置参数到 config.txt 文件中
新建 nacos-config.sh 文件,同时复制 nacos bash 脚本到 nacos-config.sh 中
使用以下命令同步配置参数到 nacos
bash nacos-config.sh -h 127.0.0.1 -p 8848 -g SEATA_GROUP -t 3a2aea46-07c6-4e21-9a1e-8946cde9e2b3 -u nacos -w nacos
得到输出
set nacosAddr=127.0.0.1:8848
set group=SEATA_GROUP
Set transport.type=TCP successfully
Set transport.server=NIO successfully
.
.
.
=========================================================================
Complete initialization parameters, total-count:80 , failure-count:0
=========================================================================
Init nacos config finished, please start seata-server.
使用 docker 部署 SEATA
Docker 部署 SEATA 官方文档
进入 TC 服务器,并进入 seat-config 文件夹
新建 registry.conf 文件,并添加以下内容,registry 配置参考
registry.conf
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos" nacos {
application = "seata-server"
group = "SEATA_GROUP"
serverAddr = "127.0.0.1"
namespace = "3a2aea46-07c6-4e21-9a1e-8946cde9e2b3"
cluster = "default"
}
} config {
# file、nacos 、apollo、zk、consul、etcd3、springCloudConfig
type = "nacos" nacos {
serverAddr = "127.0.0.1"
namespace = "3a2aea46-07c6-4e21-9a1e-8946cde9e2b3"
group = "SEATA_GROUP"
username = "nacos"
password = "nacos"
}
}
新建 file.conf 文件并添加以下内容(可选,可通过 nacos 读取)
file.conf
transport {
# tcp udt unix-domain-socket
type = "TCP"
#NIO NATIVE
server = "NIO"
#enable heartbeat
heartbeat = true
# the client batch send request enable
enableClientBatchSendRequest = true
#thread factory for netty
threadFactory {
bossThreadPrefix = "NettyBoss"
workerThreadPrefix = "NettyServerNIOWorker"
serverExecutorThread-prefix = "NettyServerBizHandler"
shareBossWorker = false
clientSelectorThreadPrefix = "NettyClientSelector"
clientSelectorThreadSize = 1
clientWorkerThreadPrefix = "NettyClientWorkerThread"
# netty boss thread size,will not be used for UDT
bossThreadSize = 1
#auto default pin or 8
workerThreadSize = "default"
}
shutdown {
# when destroy server, wait seconds
wait = 3
}
serialization = "seata"
compressor = "none"
}
service {
#transaction service group mapping
vgroupMapping.my_test_tx_group = "default"
#only support when registry.type=file, please don't set multiple addresses
default.grouplist = "127.0.0.1:8091"
#degrade, current not support
enableDegrade = false
#disable seata
disableGlobalTransaction = false
} client {
rm {
asyncCommitBufferLimit = 10000
lock {
retryInterval = 10
retryTimes = 30
retryPolicyBranchRollbackOnConflict = true
}
reportRetryCount = 5
tableMetaCheckEnable = false
reportSuccessEnable = false
}
tm {
commitRetryCount = 5
rollbackRetryCount = 5
}
undo {
dataValidation = true
logSerialization = "jackson"
logTable = "undo_log"
}
log {
exceptionRate = 100
}
}
运行 docker 命令
- 注意: 当在 config.txt 中配置 store.mode=db 时,需要在配置的数据库连接中初始化表
global_table
、branch_table
、lock_table
,sql 传送门。
docker run -d --name seata-server \
--net=host \
-p 8091:8091 \
-e SEATA_CONFIG_NAME=file:/root/seata-config/registry \
-v /root/seata-config:/root/seata-config \
seataio/seata-server:1.4.1
挂载目录为 TC 服务器配置目录。
- 注意: 当在 config.txt 中配置 store.mode=db 时,需要在配置的数据库连接中初始化表
TM (Transaction Manager) - 事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。
例子:业务聚合服务
SEATA 包引入。pom 配置如下,当使用
spring-cloud-starter-openfeign
包时,需要移除spring-cloud-starter-openfeign
包,spring-cloud-starter-alibaba-seata
中已经包含了spring-cloud-starter-openfeign
,再次引入可能导致包冲突。pom.xml
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2.2.1.RELEASE</version>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</exclusion>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
</exclusion>
</exclusions>
</dependency>
添加 registry.conf。在工程中 resource 目录下添加如下内容
registry.conf
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos" nacos {
application = "seata-server"
serverAddr = "127.0.0.1:8848"
namespace = "3a2aea46-07c6-4e21-9a1e-8946cde9e2b3"
cluster = "default"
username = "nacos"
password = "nacos"
}
} config {
# file、nacos 、apollo、zk、consul、etcd3、springCloudConfig
type = "nacos" nacos {
serverAddr = "127.0.0.1:8848"
namespace = "3a2aea46-07c6-4e21-9a1e-8946cde9e2b3"
group = "SEATA_GROUP"
username = "nacos"
password = "nacos"
}
}配置 bootstrap.properties,添加配置,内容如下,
seata.tx-service-group
和namespace
改为对应的值bootstrap.properties
...
seata.tx-service-group=app-server-tx-group
seata.config.type=nacos
seata.config.nacos.server-addr=127.0.0.1:8848
seata.config.nacos.namespace=3a2aea46-07c6-4e21-9a1e-8946cde9e2b3
seata.config.nacos.group=SEATA_GROUP
在 TM 中通过 @GlobalTransactional
开启全局异常,示例代码:
@GlobalTransactional
@GetMapping({"create"})
public String create(String name,Integer age) {
...
return "创建成功";
}
RM (Resource Manager) - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
例子:被调用服务。
配置 bootstrap.properties,添加配置,内容如下,
seata.tx-service-group
和namespace
改为对应的值bootstrap.properties
...
seata.tx-service-group=app-server-tx-group
seata.config.type=nacos
seata.config.nacos.server-addr=127.0.0.1:8848
seata.config.nacos.namespace=3a2aea46-07c6-4e21-9a1e-8946cde9e2b3
seata.config.nacos.group=SEATA_GROUP
对需要做回滚的业务标记
@Transactional(rollbackFor = Exception.class)
如果配置了全局异常处理,使用 SEATA API 发起事务回滚
@ExceptionHandler(value = Exception.class)
@ResponseBody
public String exceptionHandler(Exception e) {
...
try {
String xid = RootContext.getXID();
if (StringUtils.isNotEmpty(xid)) {
GlobalTransactionContext.reload(RootContext.getXID()).rollback();
}
} catch (TransactionException transactionException) {
transactionException.printStackTrace();
log.error("===TransactionException==={}", transactionException.getMessage());
}
return e.getMessage();
}
或者通过 AOP 全局处理回滚
/**
* @author Zhang_Xiang
* @since 2021/2/22 17:36:16
*/
@Aspect
@Component
@Slf4j
public class TxAspect { @Pointcut("execution(public * *(..))")
public void publicMethod() {
} @Pointcut("within(com.*.service.impl..*)")
private void services() {
} @Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
private void transactional() {
} @Pointcut("within(com.*.webapi.controller..*)")
private void actions() {
} @Pointcut("@annotation(org.springframework.web.bind.annotation.ExceptionHandler))")
private void validatedException() {
} @Before(value = "validatedException()")
public void beforeValidate(JoinPoint joinPoint) throws TransactionException {
Object[] args = joinPoint.getArgs();
if (args == null || args.length == 0) {
return;
}
Exception e = (Exception) args[0];
if (e instanceof MethodArgumentNotValidException || e instanceof BindException || e instanceof
ConstraintViolationException) {
globalRollback();
}
} @AfterThrowing(throwing = "e", pointcut = "publicMethod()&&services()&&transactional()")
public void doRecoveryMethods(Throwable e) throws TransactionException {
log.info("===method throw===:{}", e.getMessage());
globalRollback();
} @AfterReturning(value = "publicMethod()&&actions()", returning = "result")
public void afterReturning(RestResponse<?> result) throws TransactionException {
log.info("===method finished===:{}", result);
if (result.isFail()) {
globalRollback();
}
} //region private methods private void globalRollback() throws TransactionException {
if (!StringUtils.isBlank(RootContext.getXID())) {
log.info("===xid===:{}", RootContext.getXID());
GlobalTransactionContext.reload(RootContext.getXID()).rollback();
}
} //endregion
}
分布式事务 SEATA-1.4.1 AT模式 配合NACOS 应用的更多相关文章
- 分布式事务 Seata Saga 模式首秀以及三种模式详解 | Meetup#3 回顾
https://mp.weixin.qq.com/s/67NvEVljnU-0-6rb7MWpGw 分布式事务 Seata Saga 模式首秀以及三种模式详解 | Meetup#3 回顾 原创 蚂蚁金 ...
- 分布式事务(Seata) 四大模式详解
前言 在上一节中我们讲解了,关于分布式事务和seata的基本介绍和使用,感兴趣的小伙伴可以回顾一下<别再说你不知道分布式事务了!> 最后小农也说了,下期会带给大家关于Seata中关于sea ...
- 阿里分布式事务seata入门(采坑)
1. 阿里分布式事务seata入门(采坑) 1.1. 前言 seata是feascar改名而来,这是阿里在19年年初开源出来的分布式事务框架,当初刚出来的时候就想研究下了,一直拖到了现在,目前是0.8 ...
- 分布式事务(Seata)原理 详解篇,建议收藏
前言 在之前的系列中,我们讲解了关于Seata基本介绍和实际应用,今天带来的这篇,就给大家分析一下Seata的源码是如何一步一步实现的.读源码的时候我们需要俯瞰起全貌,不要去扣一个一个的细节,这样我们 ...
- SpringCloud系列之集成分布式事务Seata应用篇
目录 前言 项目版本 项目说明 Seata服务端部署 Seata客户端集成 cloud-web module-order module-cart module-goods module-wallet ...
- 出席分布式事务Seata 1.0.0 GA典礼
前言 图中那个红衣服的就是本人 什么是分布式事务 分布式事务就是指事务的参与者.支持事务的服务器.资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上. 简单的说,就是一次大的操作由不同的小 ...
- 微服务开发的最大痛点-分布式事务SEATA入门简介
前言 在微服务开发中,存在诸多的开发痛点,例如分布式事务.全链路跟踪.限流降级和服务平滑上下线等.而在这其中,分布式事务是最让开发者头痛的.那分布式事务是什么呢? 分布式事务就是指事务的参与者.支持事 ...
- SpringCloud整合分布式事务Seata 1.4.1 支持微服务全局异常拦截
项目依赖 SpringBoot 2.5.5 SpringCloud 2020.0.4 Alibaba Spring Cloud 2021.1 Mybatis Plus 3.4.0 Seata 1.4. ...
- spring boot:使用分布式事务seata(druid 1.1.23 / seata 1.3.0 / mybatis / spring boot 2.3.2)
一,什么是seata? Seata:Simpe Extensible Autonomous Transcaction Architecture, 是阿里中间件开源的分布式事务解决方案. 前身是阿里的F ...
随机推荐
- redis学习教程二《四大数据类型》
redis学习教程二<四大数据类型> 四大数据类型包括:字符串 哈希 列表 集合一 : Redis字符串 Redis字符串命令用于管理Redis中的字符串 ...
- 3. Linux常用系统状态检测命令
1.ifconfig :于获取网卡配置与网络状态等信息,如网卡名称.IP.MAC等 2.uname -a :完整地查看当前系统的内核名称.主机名.内核发行版本.节点名.系统时间.硬件名称.硬件平台.处 ...
- Linux数据库的导入导出
Linux数据库的导入导出 1.导入数据库 mysql -u username -p test < /home/data/test.sql 说明:username是数据库用户名,test为目标数 ...
- CCF-I'm stuck!(BFS)
I'm stuck! 问题描述 给定一个R行C列的地图,地图的每一个方格可能是'#', '+', '-', '|', '.', 'S', 'T'七个字符中的一个,分别表示如下意思: '#': 任何 ...
- Java泛型学习---第二篇
泛型学习第一篇 1.泛型之擦拭法 泛型是一种类似"模板代码"的技术,不同语言的泛型实现方式不一定相同. Java语言的泛型实现方式是擦拭法(Type Erasure). 所谓擦拭法 ...
- Flink-v1.12官方网站翻译-P009-Event-driven Applications
事件驱动的应用 处理函数 简介 ProcessFunction将事件处理与定时器和状态结合起来,使其成为流处理应用的强大构件.这是用Flink创建事件驱动应用的基础.它与RichFlatMapFunc ...
- Codeforces Round #664 (Div. 2) C. Boboniu and Bit Operations
传送门:cf1395C 题意 c[i]=a[i]&b[j],b[j]是b数组中任意一个,求c[1] | c[2] | ... | c[n]最小值. 题解 经典的二进制枚举答案,因为a和b的最大 ...
- 【noi 2.2_7891】一元三次方程求解(二分枚举+输出程序运行时间)
对于noi上的题有2种解法: 1.数据很小(N=100),可以直接打for循环枚举和判断. 2.不会"三分",便用二分.利用"两根相差>=1"和 f(x1 ...
- hdu2157 How many ways??
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission ...
- Codeforces Round #654 (Div. 2) B. Magical Calendar (结论)
题意:你需要在长度从\(1\)~\(k\),宽度无限的网格图中造图形(每个点四周必须连通),问最多能造出多少种不同的图形. 题解:感觉没什么好说的,就是画图找规律,如果\(r\ge n\)的话(即没有 ...