记录:微服务项目集成seata分布式事务框架坑点测试
1.背景
项目需要进行重构,从单体架构改为微服务项目,RPC框架为spring cloud alibaba,分布式事务框架为seata。由于本人没有用过seata,所以在项目框架搭建之处,未有考虑过一些坑点。本文就其中一个内层服务重试方面的坑做了简单的测试。
2.坑点猜测
ribbon 和 feign 都是有重试的(本项目并没有采用ribbon重试,而是采用的feign重试),而当前项目并没有特殊的去做幂等,只是考虑通过数据版本来控制并发。所以猜想:某些场景(无唯一性校验或者业务数据验证)会因为重试造成逻辑重复执行,造成数据重写。
3.坑点验证
3.1.服务调用关系
外层服务:TestSeataService;依次调用内层事务:iTestBasicService,iTestInboundService
重试的内层服务是:iTestBasicService
3.2.外层事务
- 代码
@Service
@AllArgsConstructor
public class TestSeataService {
private ITestBasicService iTestBasicService;
private ITestInboundService iTestInboundService;
@GlobalTransactional
public void test(Long id, String code) {
//依次调用两个内层服务
iTestBasicService.insert(id, code);
iTestInboundService.insert(id, code);
}
}
- 超时配置
feign:
hystrix:
enabled: true
httpclient:
enabled: true
client:
config:
default:
connectTimeout: 1000
readTimeout: 5000 #超时时间:5S
3.3.内层事务
- TestBasicService
@Service
@AllArgsConstructor
@Transactional
public class TestBasicService {
private static Long time = 23000L;
private TestBasicMapper testBasicMapper;
public Integer insert(Long id, String code) throws InterruptedException {
//通过全局变量递减来模拟请求从超时到不超时的场景
Thread.sleep( time -= 5000);
TestBasic basic = new TestBasic(id, code);
testBasicMapper.insert(basic));
return 1;
}
}
- TestInboundService
@Service
@AllArgsConstructor
@Transactional
public class TestInboundService {
private TestInboundMapper testInboundMapper;
public Integer insert(Long id, String code) {
TestInbound basic = new TestInbound(id, code);
testInboundMapper.insert(basic);
return 1;
}
}
3.4.结果输出
调用接口,参数如下:id=内部生成;code=15
-
日志
//待补充
-
数据
表 test_basic:
id code 10000000971 15 10000000972 15 表 test_inbound:
id code 10000001062 15
4.结论
没有进行幂等支持的话,重试确实会产生数据问题。
5.未测试点
- ribbon 和 feign重试均没有配置时,为什么没用5S 超时回滚,而是等待了23S执行成功了
- TestBasicService 调用结束,服务挂掉的场景