SpringBoot集成Dubbo LCN进行分布式事务管理

5 篇文章 0 订阅
1 篇文章 0 订阅

#前言
在之前的spring+dubbo进行分布式项目搭建时,在面对被@Transactionnal()注解的事务服务时,dubbo是不能将其注册成服务者的。
查阅资料后发现大致原因:是因为我们一般的service发布dubbo服务时,dubbo能够扫描到类上dubbo的@service注解,并为其生成代理,而当我们使用@Transactionnal注解时,将会采用cglib为service生成代理,生成的类为原service的子类,而bubbo并没有允许子类继承父类的注解,因此就扫描不到这个注解并生成代理了。
解决方法可参考博客:http://blog.csdn.net/verne_feng/article/details/53022088

#背景

在事务成功注册上之后,远程多数据库跨服务跨库回滚成为亟待解决的难题。参考大量资料后发现,这是一个通用的世界性难题,而向阿里腾讯一些大团队,他们应用的也无非是使用以下两中方式结合使用:

1、使用各种MQ消息中间件进行事务代理,涉及事务问题多采用两段式或三段式提交,并尽量将事务拆分成本地事务串行。

2、使用本地消息库进行消息存储,因为消息中间件具有一定的不可靠性,所以使用本地库作为一种弥补。

首先呢,通过多方调研,我们不可否认,上述做法具有其特定的优越性。因为从大数据量、高并发以及亿级用户压力角度来讲。上述方式也许是唯一一种比较可行的方式。

但结合我们的实际环境和需求,上述方式并不能解决我们对事务的完整回滚操作。后经过调研发现DUBBO LCN可以完成这项使命。DUBBO LCN是将我们的事务进行标注,形成一个事务组,当我们需要回滚的时候,控制事务组回滚即可。这样将一个个子事务的回滚交给其所在的数据库,由数据库单独执行回滚。可行性很高。

当然,同样站在用户压力角度看,我猜想LCN可能并不能承受很高的压力,因为每次我们都需要标注事务,形成事务组,当事务链又多又长的时候,其性能可以想象,肯定高不了。但是站在我们当前的小站点来说,当用户压力并不足以造成巨大的影响时,使用LCN将是我们的首选。因为其简洁明了,只需要在本地事务上将本地事务标注为tx-manager事务,添加或生成事务组即可。

#配置

在明白了LCN的背景及其作用域后,我们开始配置环境。

1、下载工具

首先,你可以参考官网,官网有更详细的讲解:
https://github.com/1991wangliang/tx-lcn

如果你需要一个直接配置好的成品开箱即用,你可以下载笔者整理好的包,按readme.txt的描述启动即可。

https://pan.baidu.com/s/1gSXd3sFmMPPFNAWVlJ_jCw

另外所需本地环境需自行下载:
zookeeper
redis

2、配置解析

参考官网配置,这里做出解释:

在LcnConfg.java中,我们添加了如下注解:


@Configuration
@EnableTransactionManagement(proxyTargetClass=true)
@ComponentScan(basePackages={"com.codingapi.tx.*","com.iking.provider.*"})
@ImportResource(locations = {"classpath*:dubbo_provider.xml"})
public class LcnConfig implements TxManagerTxUrlService{
	
	@Autowired
    private Environment env;
	
	/**
	 * 获取代理连接池
	 * @return
	 */
    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(env.getProperty("spring.datasource.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.username"));
        dataSource.setPassword(env.getProperty("spring.datasource.password"));
        return dataSource;
    }
	
	/**
	 * 注入LCN的代理连接池
	 * @return
	 */
	@Bean("transactionManager")
	public PlatformTransactionManager txManager(){
		return new DataSourceTransactionManager(dataSource());
	}

	@Override
	public String getTxUrl() {
		return env.getProperty("tx.manager.url");
	}
	
}

1)首先呢,我们将此类标注为全局配置类,使用@Configuration
2)我们使用@EnableTransactionManagement(proxyTargetClass=true)开启事务远程代理,并进行连接池和LCN代理的注入:


@Autowired
private Environment env;

/**
 * 获取代理连接池
 * @return
 */
@Bean
public DataSource dataSource() {
    DruidDataSource dataSource = new DruidDataSource();
    dataSource.setUrl(env.getProperty("spring.datasource.url"));
    dataSource.setUsername(env.getProperty("spring.datasource.username"));
    dataSource.setPassword(env.getProperty("spring.datasource.password"));
    return dataSource;
}

/**
 * 注入LCN的代理连接池
 * @return
 */
@Bean("transactionManager")
public PlatformTransactionManager txManager(){
    return new DataSourceTransactionManager(dataSource());
}

这个注解等同于官网上xml中的下列代码:


    <!--lcn代理连接池配置-->
<bean name="lcnDataSourceProxy" class="com.lorne.tx.db.LCNDataSourceProxy">
    <property name="dataSource" ref="dataSource"/>
      <!-- 分布式事务参与的最大连接数,确保不要超过普通连接池的最大值即可 -->
    <property name="maxCount" value="20"/>
</bean>


<!--jdbcTemplate -->
<bean id="jdbcTemplate"
      class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource">
        <ref bean="lcnDataSourceProxy"/>
    </property>
</bean>
    
<!--jdbc事务配置 -->
<bean id="transactionManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="lcnDataSourceProxy" />
</bean>

以及:


<tx:annotation-driven/>


<!-- Aspect -->
<aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true"/>

3)使用@ComponentScan(basePackages={“com.codingapi.tx.","com.iking.provider.”})扫描lcn以及本项目相关路径,等同于官网demo中的:


<context:component-scan base-package="com.codingapi.tx.*"/>

4)最后,我们实现了TxManagerTxUrlService接口,将tx-manager的路径进行自定义配置:


public class LcnConfig implements TxManagerTxUrlService{


@Override
public String getTxUrl() {
	return env.getProperty("tx.manager.url");
}

application.properties中添加路径配置即可:


#tx-manager
tx.manager.url=http://127.0.0.1:8899/tx/manager/

5)最后,我们将dubbo_provider.xml引进来:


@ImportResource(locations = {"classpath*:dubbo_provider.xml"})

等同于官网上的下列配置:

配置介绍到此为止,即可进行测试,如有疑问,烦请@笔者:Q:980420579 Q群:697819474

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值