Spring Boot微服务如何集成fescar解决分布式事务问题?
什么是fescar?
关于fescar的详细介绍,请参阅fescar wiki。
传统的2PC提交协议,会持有一个全局性的锁,所有局部事务预提交成功后一起提交,或有一个局部事务预提交失败后一起回滚,最后释放全局锁。锁持有的时间较长,会对并发造成较大的影响,死锁的风险也较高。
fescar的创新之处在于,每个局部事务执行完立即提交,释放本地锁;它会去解析你代码中的sql,从数据库中获得事务提交前的事务资源即数据,存放到undo_log中,全局事务协调器在回滚的时候直接使用undo_log中的数据覆盖你提交的数据。
Spring Boot如何集成fescar?
我们可以从官方代码库中看到,fescar目前提供的示例是针对使用dubbo的服务,那Spring Boot的项目如何集成fescar呢?
和很多2PC提交协议(如tx_lcn)的解决方案一样,fescar也是在数据源处做了代理,和事务协调器进行通信,来决定本地事务是否回滚。所以,第一步,在你的spring boot项目中,首先应使用fescar提供的代理数据源作为你的数据源,例如:
DruidDataSource dataSource = initDataSource(dataSourceProps.get("url").toString(), dataSourceProps.get("username").toString(), dataSourceProps.get("password").toString());
DataSourceProxy proxy = new DataSourceProxy(dataSource);
然后,你需要创建一个Feign拦截器,把RootContext中的XID(XID用于标识一个局部事务属于哪个全局事务,需要在调用链路的上下文中传递)传递到上层调用链路。
@Component
public class RequestHeaderInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
String xid = RootContext.getXID();
if(StringUtils.isNotBlank(xid)){
template.header("Fescar-Xid",xid);
}
}
}
最后,你需要创建一个Http Rest请求拦截器,用于把当前上下文中获取到的XID放到RootContext。
import com.alibaba.fescar.core.context.RootContext;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; public class FescarXidFilter extends OncePerRequestFilter {
protected Logger logger = LoggerFactory.getLogger(FescarXidFilter.class); @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String xid = RootContext.getXID();
String restXid = request.getHeader("Fescar-Xid");
boolean bind = false;
if(StringUtils.isBlank(xid)&&StringUtils.isNotBlank(restXid)){
RootContext.bind(restXid);
bind = true;
if (logger.isDebugEnabled()) {
logger.debug("bind[" + restXid + "] to RootContext");
}
}
try{
filterChain.doFilter(request, response);
} finally {
if (bind) {
String unbindXid = RootContext.unbind();
if (logger.isDebugEnabled()) {
logger.debug("unbind[" + unbindXid + "] from RootContext");
}
if (!restXid.equalsIgnoreCase(unbindXid)) {
logger.warn("xid in change during http rest from " + restXid + " to " + unbindXid);
if (unbindXid != null) {
RootContext.bind(unbindXid);
logger.warn("bind [" + unbindXid + "] back to RootContext");
}
}
}
}
}
}
这样就完成了fescar的集成。
开始使用吧!
首先在项目中初始化两个Bean:
@Bean
public FescarXidFilter fescarXidFilter(){
return new FescarXidFilter();
} @Bean
public GlobalTransactionScanner scanner(){
GlobalTransactionScanner scanner = new GlobalTransactionScanner("fescar-test","my_test_tx_group");
return scanner;
}
然后写两个服务,服务A调用服务B,并在A服务的调用方法上打上@GlobalTransactional标签:
@GlobalTransactional(timeoutMills = 300000, name = "fescar-test-tx")
public void testFescar() throws BusinessException {
DictionVO dictionVO = new DictionVO();
dictionVO.setCode("simidatest");
dictionVO.setValue("1");
dictionVO.setDesc("simidatest");
dictionVO.setAppId("sso");
commonService.createDiction(dictionVO);//远程调用服务B
areaMapper.deleteAreaBySysNo(2);//本地事务 throw new BusinessException("主动报错");
}
最后,两个项目中添加application.conf文件,用于告诉客户端如何与分布式协调器通信,官方示例中有这个文件,就不在此贴代码啦,application.conf传送门
启动事务协调器,sh fescar-server.sh 8091 ~/dksl/git/fescar/data,启动你的项目,开始测试吧!
demo地址:https://github.com/dk-lockdown/seata-demo
集成代码:dk-foundation seata分支(https://github.com/dk-lockdown/dk-foundation/tree/dev-seata)
last thing
分布式事务作为微服务应用中的老大难问题,在现有的解决方案中,个人认为fescar是目前最轻量并且代价最小的一种解决方案。目前的版本,事务协调器还不能分布式部署,官方给出的路线图是在三月底会有第一个生产可用版本。让我们一起参与到fescar的社区中,共同推动fescar生态建设,让落地微服务不必再担心分布式事务的问题。
Spring Boot微服务如何集成fescar解决分布式事务问题?的更多相关文章
- Spring Boot 微服务应用集成Prometheus + Grafana 实现监控告警
Spring Boot 微服务应用集成Prometheus + Grafana 实现监控告警 一.添加依赖 1.1 Actuator 的 /prometheus端点 二.Prometheus 配置 部 ...
- 【原创】Docker容器及Spring Boot微服务应用
Docker容器及Spring Boot微服务应用 1 什么是Docker 1.1 Docker的出现 问题一:项目实施环境复杂问题 传统项目实施过程中经常会出现“程序在我这跑得好好的,在你那怎么就不 ...
- 【spring boot】spring cloud下spring boot微服务启动没有报错,但是访问访问不到
spring cloud下spring boot微服务启动没有报错,但是访问访问不到 解决方法: 可能是端口被占用了,但是依旧启用成功了. 更改一下项目启用的端口号,再重新启动查看是否可以正常访问.
- Spring Boot微服务架构入门
概述 还记得在10年毕业实习的时候,当时后台三大框架为主流的后台开发框架成软件行业的标杆,当时对于软件的认识也就是照猫画虎,对于为什么会有这么样的写法,以及这种框架的优势或劣势,是不清楚的,Sprin ...
- 基于Centos7.4搭建prometheus+grafana+altertManger监控Spring Boot微服务(docker版)
目的:给我们项目的微服务应用都加上监控告警.在这之前你需要将 Spring Boot Actuator引入 本章主要介绍 如何集成监控告警系统Prometheus 和图形化界面Grafana 如何自定 ...
- 使用http://start.spring.io/构建maven微服务项目的几个坑及eclipse构建spring boot微服务项目
一,使用http://start.spring.io/构建maven微服务项目 本来嘛,直接构建的项目导入时没有任何问题的导入就可以运行,可是最近构建好项目,然后导入,种种报错 1.导入之后POM报错 ...
- 在spring boot微服务中使用JWS发布webService
发布时间:2018-11-22 技术:Java+spring+maven 概述 在springboot微服务中使用JWS发布webService,在服务启动时自动发布webservice接口. ...
- Spring Boot微服务框架的搭建
(1)spring boot简介 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发 ...
- Spring Boot微服务电商项目开发实战 --- 基础配置及搭建
根据SpringBoot实现分布式微服务项目近两年的开发经验,今天决定开始做SpringBoot实现分布式微服务项目的系列文章,帮助其他正在使用或计划使用SringBoot开发的小伙伴们.本次系列文章 ...
随机推荐
- hdu 1518 BFS
Given a set of sticks of various lengths, is it possible to join them end-to-end to form a square? I ...
- Leetcode 两数之和 (散列表)
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2, 7, 11, 15], target ...
- Windows与Linux的命令行命令对比
Windows与Linux的命令行命令对比 * Windows不区分大小写,Linux区分大小写的. sn DOS Command UNIX Equivalent Effect 影响 1 ASSIGN ...
- qt+opencv LNK4272:library machine type 'x64' conflicts with target mathine type 'x86'
运行时报错如上图所示,原因是你使用的opencv库是64位的,qt里面使用的编译器MSVC是32位的,解决方法如下: 将构建套件修改位64bit:
- Java中HBase的集中過濾器
比較過濾器: rowKey过滤器 RowFilter 列族过滤器 FamilyFilter 列过滤器 QualifierFilter 列值过滤器 ...
- Python练习七
1.写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者. def func(dic): for k in dic: if len(dic[k] ...
- 单线拨号上网时RouterOS内网端口映射的配置
很多时候routeros 是通过单线拨号上网,假设PPP接口名为pppoe-out1 若需要添加内网ip=18.16.1.92主机的3389端口映射 ,可以在命令行键入: ip firewall na ...
- 初学git,初始化库|添加文件ignore|提交方法
1.初始化git仓库: 进入任意目录,右键选择:Git Bash Here,输入命令:git status 查看当前git库的状态. 如要排除文件,在库根目录下创建.gitignore文件(新建文件改 ...
- 《Self-Attention Generative Adversarial Networks》里的注意力计算
前天看了 criss-cross 里的注意力模型 仔细理解了 在: https://www.cnblogs.com/yjphhw/p/10750797.html 今天又看了一个注意力模型 < ...
- click python cli 开发包
python click 包是一个方便的cli 开发包,我们可以用来开发强大的cli 应用 使用venv 进行环境准备,示例代码来自官方 venv 环境准备 python3 -m venv demoa ...