Spring Boot Druid 多数据源 Atomikos 分布式事务

来源:互联网 发布:金山软件太原公司 编辑:程序博客网 时间:2024/04/27 07:18

1、前言

由于最近需要做一个接口平台,用到了两个数据库(业务库和系统库分离),需要考虑同时操作两个数据库的数据时事务的管理,这时搜索了下资料,发现使用分布式事务可满足现状需求。之前也没接触过分布式事务,在baidu、google了一遍之后,根据相关的示例也未成功搭建。在一番折腾之后,终于搭建成功, 现将其记录下来,也为将来有此需求的朋友提供一点帮助。

2、名词解释

1、Spring Boot:Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。官网地址:http://projects.spring.io/spring-boot/

2、Druid:阿里的JDBC连接池组件,详细参考:https://github.com/alibaba/druid

3、分布式事务 : 参考博客(http://www.cnblogs.com/zengkefu/p/5742617.html)

4、Atomikos:一个为Java平台提供增值服务的并且开源类事务管理器。

3、环境搭建

1、项目目录结构(maven项目):

这里写图片描述

2、pom.xml

<properties>    <spring.boot.version>1.5.4.RELEASE</spring.boot.version>    <druid.version>1.0.31</druid.version></properties><dependencies>    <!-- spring boot begin -->    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-web</artifactId>        <version>${spring.boot.version}</version>        <exclusions>            <!-- 排除spring boot默认使用的tomcat,使用jetty -->            <exclusion>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-starter-tomcat</artifactId>            </exclusion>        </exclusions>    </dependency>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-jetty</artifactId>        <version>${spring.boot.version}</version>    </dependency>    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc -->    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-jdbc</artifactId>        <version>${spring.boot.version}</version>    </dependency>    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jta-atomikos -->    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-jta-atomikos</artifactId>        <version>${spring.boot.version}</version>    </dependency>    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-test</artifactId>        <version>${spring.boot.version}</version>    </dependency>    <!-- spring boot end -->    <!-- alibaba database pool begin -->    <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->    <dependency>        <groupId>com.alibaba</groupId>        <artifactId>druid</artifactId>        <version>${druid.version}</version>    </dependency>    <dependency>        <groupId>com.alibaba</groupId>        <artifactId>druid-spring-boot-starter</artifactId>        <version>1.1.1</version>    </dependency>    <!-- alibaba database pool end -->    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->    <dependency>        <groupId>mysql</groupId>        <artifactId>mysql-connector-java</artifactId>        <version>5.1.42</version>    </dependency></dependencies>

3、application.yml

#日志配置#日志配置,此处使用默认日志#logging:#  config: classpath:log4j2.yml# springspring:  profiles:    active:      - test  datasource:    type: com.alibaba.druid.pool.xa.DruidXADataSource    druid:      # WebStatFilter配置,说明请参考Druid Wiki,配置_配置WebStatFilter      web-stat-filter:        enabled: true         urlPattern:         exclusions:        sessionStatMaxCount:        sessionStatEnable:        principalSessionName:        principalCookieName:        profileEnable:      # StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置        stat-view-servlet:        enabled: true        urlPattern:         resetEnable: false         loginUsername: admin        loginPassword: 123456        allow: 127.0.0.1        deny:      # Spring监控配置,说明请参考Druid Github Wiki,配置_Druid和Spring关联监控配置     # Spring监控AOP切入点,如x.y.z.service.*,配置多个英文逗号分隔      aop-patterns:        - com.chint.springboot.atomikos.*.service.**      systemDB:        name: systemDB        url: jdbc:mysql://localhost/test_sys        username: root        password: 123456a        # 下面为连接池的补充设置,应用到上面所有数据源中        # 初始化大小,最小,最大        initialSize: 5        minIdle: 5        maxActive: 20        # 配置获取连接等待超时的时间        maxWait: 60000        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒         timeBetweenEvictionRunsMillis: 60000        # 配置一个连接在池中最小生存的时间,单位是毫秒         minEvictableIdleTimeMillis: 30        validationQuery: SELECT 1         validationQueryTimeout: 10000        testWhileIdle: true        testOnBorrow: false        testOnReturn: false        # 打开PSCache,并且指定每个连接上PSCache的大小         poolPreparedStatements: true        maxPoolPreparedStatementPerConnectionSize: 20        filters: stat,wall        # 通过connectProperties属性来打开mergeSql功能;慢SQL记录        connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000        # 合并多个DruidDataSource的监控数据        useGlobalDataSourceStat: true       businessDB:        name: businessDB        url: jdbc:mysql://localhost/test_bus        username: root        password: 123456a        # 下面为连接池的补充设置,应用到上面所有数据源中        # 初始化大小,最小,最大        initialSize: 5        minIdle: 5        maxActive: 20        # 配置获取连接等待超时的时间        maxWait: 60000        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒         timeBetweenEvictionRunsMillis: 60000        # 配置一个连接在池中最小生存的时间,单位是毫秒         minEvictableIdleTimeMillis: 30        validationQuery: SELECT 1         validationQueryTimeout: 10000        testWhileIdle: true        testOnBorrow: false        testOnReturn: false        # 打开PSCache,并且指定每个连接上PSCache的大小         poolPreparedStatements: true        maxPoolPreparedStatementPerConnectionSize: 20        filters: stat,wall        # 通过connectProperties属性来打开mergeSql功能;慢SQL记录        connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000        # 合并多个DruidDataSource的监控数据        useGlobalDataSourceStat: true   #jta相关参数配置     jta:    log-dir: classpath:tx-logs    transaction-manager-id: txManager

4、DataSourceConfig.java

package com.zzmx.springboot.atomikos.config;import java.util.Properties;import javax.sql.DataSource;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import org.springframework.core.env.Environment;import org.springframework.jdbc.core.JdbcTemplate;@Configurationpublic class DataSourceConfig {    @Bean(name = "systemDataSource")    @Primary    @Autowired    public DataSource systemDataSource(Environment env) {        AtomikosDataSourceBean ds = new AtomikosDataSourceBean();        Properties prop = build(env, "spring.datasource.druid.systemDB.");        ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");        ds.setUniqueResourceName("systemDB");        ds.setPoolSize(5);        ds.setXaProperties(prop);        return ds;    }    @Autowired    @Bean(name = "businessDataSource")    public AtomikosDataSourceBean businessDataSource(Environment env) {        AtomikosDataSourceBean ds = new AtomikosDataSourceBean();        Properties prop = build(env, "spring.datasource.druid.businessDB.");        ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");        ds.setUniqueResourceName("businessDB");        ds.setPoolSize(5);        ds.setXaProperties(prop);        return ds;    }    @Bean("sysJdbcTemplate")    public JdbcTemplate sysJdbcTemplate(@Qualifier("systemDataSource") DataSource ds) {        return new JdbcTemplate(ds);    }    @Bean("busJdbcTemplate")    public JdbcTemplate busJdbcTemplate(@Qualifier("businessDataSource") DataSource ds) {        return new JdbcTemplate(ds);    }    private Properties build(Environment env, String prefix) {        Properties prop = new Properties();        prop.put("url", env.getProperty(prefix + "url"));        prop.put("username", env.getProperty(prefix + "username"));        prop.put("password", env.getProperty(prefix + "password"));        prop.put("driverClassName", env.getProperty(prefix + "driverClassName", ""));        prop.put("initialSize", env.getProperty(prefix + "initialSize", Integer.class));        prop.put("maxActive", env.getProperty(prefix + "maxActive", Integer.class));        prop.put("minIdle", env.getProperty(prefix + "minIdle", Integer.class));        prop.put("maxWait", env.getProperty(prefix + "maxWait", Integer.class));        prop.put("poolPreparedStatements", env.getProperty(prefix + "poolPreparedStatements", Boolean.class));        prop.put("maxPoolPreparedStatementPerConnectionSize",                env.getProperty(prefix + "maxPoolPreparedStatementPerConnectionSize", Integer.class));        prop.put("maxPoolPreparedStatementPerConnectionSize",                env.getProperty(prefix + "maxPoolPreparedStatementPerConnectionSize", Integer.class));        prop.put("validationQuery", env.getProperty(prefix + "validationQuery"));        prop.put("validationQueryTimeout", env.getProperty(prefix + "validationQueryTimeout", Integer.class));        prop.put("testOnBorrow", env.getProperty(prefix + "testOnBorrow", Boolean.class));        prop.put("testOnReturn", env.getProperty(prefix + "testOnReturn", Boolean.class));        prop.put("testWhileIdle", env.getProperty(prefix + "testWhileIdle", Boolean.class));        prop.put("timeBetweenEvictionRunsMillis",                env.getProperty(prefix + "timeBetweenEvictionRunsMillis", Integer.class));        prop.put("minEvictableIdleTimeMillis", env.getProperty(prefix + "minEvictableIdleTimeMillis", Integer.class));        prop.put("filters", env.getProperty(prefix + "filters"));        return prop;    }}

5、Application.java

package com.zzmx.springboot.atomikos;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Import;import org.springframework.transaction.annotation.EnableTransactionManagement;import com.zzmx.springboot.atomikos.config.DataSourceConfig;@EnableAutoConfiguration@ComponentScan("com.zzmx.springboot.atomikos")@Configuration@EnableTransactionManagement(proxyTargetClass = true)@Import({ DataSourceConfig.class })public class Application {    public static void main(String[] args) throws Exception {        SpringApplication.run(Application.class, args);    }}

6、测试效果
这里写图片描述

根据spring boot官方文档描述,如果spring boot检测到了jta环境,会自动进行配置,故此处不需要进行事务配置,官方地址:http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-jta.html

TransactionManagerConfig.java 是为junit测试事务而写的,由于本人对这块不太清楚,没有完成,测试暂时使用controller代替。

源码下载地址:https://github.com/zhouyuntao/springboot-atomikos

阅读全文
0 0
原创粉丝点击