场景:有A和B两个服务,均已集成nacos、seata服务。
A服务中修改表数据后再调B服务,B服务中再保存一条数据。服务之间用Http形式调用(dubbo调用肯定没问题,已在用)
期望:保持事务一致性,不希望出现A服务修改数据成功,B服务保存数据失败,要么都成功,要么都失败。
实现:正常情况下是没问题的,出异常后事物回滚需要验证。
A服务: 调用B服务后,制造一个异常信息。
Map<String, String> params = Maps.newHashMap();
params.put("username", "123");
JSONObject postResult = HttpUtils.post("http://localhost:8081/ipc-report/test/save",
params, JSONObject.class);
System.out.println("------:" + JSONUtil.toJsonStr(postResult));
int i = 1 / 0;
HttpUtils.post方法内容如下:
HttpPost post = new HttpPost(url);
if (StringUtil.isNotEmpty(postData)) {
post.addHeader("Content-type", "application/json");
post.addHeader("token", "123");
post.addHeader("loginSource", "1");
post.addHeader(RootContext.KEY_XID, RootContext.getXID());
StringEntity entity = new StringEntity(postData, "UTF-8");
post.setEntity(entity);
}
B服务:获得header中的数据,并保存一条数据
@ApiOperation(value = "添加用户")
@PostMapping("/save")
public ApiResult<Boolean> save(@Validated @RequestBody TestUserSaveModel saveModel, HttpServletRequest request) {
String token = request.getHeader("token");
String loginSource = request.getHeader("loginSource");
String username = saveModel.getUsername();
System.out.println("----- token: " + token);
System.out.println("----- loginSource: " + loginSource);
System.out.println("----- username: " + username);
testUserService.saveUser(saveModel);
return ApiResult.success("添加用户成功", true);
}
结果:
B服务日志如下:
A服务日志如下:
seata也是直接通过mvc中拦截器去获取事务ID,只要在请求头上附上对应的header即可:
post.addHeader(RootContext.KEY_XID, RootContext.getXID());