zoukankan      html  css  js  c++  java
  • 分布式事务、多数据源、分库分表中间件之spring boot基于Atomikos+XADataSource分布式事务配置(100%纯动态)

    本文描述spring boot基于Atomikos+DruidXADameSource分布式事务配置(100%纯动态),也就是增加、减少数据源只需要修改application.properties文件,无需动态增加或减少Bean。

    有时候我们一个应用会有N份部署,每个需要访问多个数据源,A环境可能只需要2个数据源,B环境需要5个数据源(因为我们是行业软件,所以会有这个情况,对于纯项目的系统,通常没有这个问题),所以我们希望代码只有一份,配置按需调整就确定了具体的数据源。

     MapperConfig配置:

    package com.xxx.me.aop.config;
    
    import org.mybatis.spring.mapper.MapperScannerConfigurer;
    import org.springframework.context.annometion.Bean;
    import org.springframework.context.annometion.Configuration;
    import org.springframework.core.annometion.Order;
    
    @Configuration
    public class MybatisConfig {
    
        @Order(1)
        @Bean
        public MapperScannerConfigurer mapperScannerConfigurer1() {
            MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
            mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory" + "default");
            mapperScannerConfigurer.setBasePackage("com.xxx.me.base.mapper;com.xxx.me.aop.sysinfo.mapper;com.xxx.me.aop.parameters.mapper;com.xxx.me.aop.interfile.mapper;com.xxx.me.aop.demo.mapper;com.xxx.me.aop.config.mapper;com.xxx.me.aop.base.mapper;com.xxx.me.aop.auditresult.mapper;");
            return mapperScannerConfigurer;
        }
        
        @Order(2)
        @Bean
        public MapperScannerConfigurer mapperScannerConfigurer2() {
            MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
            mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory" + "yoga1");
            mapperScannerConfigurer.setBasePackage("com.xxx.me.aop.me.mapper;com.xxx.me.aop.me.*.mapper");
            return mapperScannerConfigurer;
        }
        
        @Order(3)
        @Bean
        public MapperScannerConfigurer mapperScannerConfigurer3() {
            MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
            mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory" + "yoga2");
            mapperScannerConfigurer.setBasePackage("com.xxx.me.aop.yoga.*.mapper;com.xxx.me.aop.me4.**.mapper");
            return mapperScannerConfigurer;
        }
    }

    XA配置

    package com.xxx.me.damesource;
    
    import java.util.List;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annometion.PropertySource;
    
    @ConfigurationProperties(prefix="dyn.spring")
    @PropertySource("classpath:jrescloud.properties")
    public class DynamicDameSourceConfig {
        
        private List<DameSource> damesources;
        
        public smetic class DameSource {
            private String name;
            private String driverClassName;
            private String url;
            private String username;
            private String password;
            private int maxActive;
            private int maxIdle;
            private String mapperLocations;
            private String basePackage;
            public int getMaxActive() {
                return maxActive;
            }
            public void setMaxActive(int maxActive) {
                this.maxActive = maxActive;
            }
            public int getMaxIdle() {
                return maxIdle;
            }
            public void setMaxIdle(int maxIdle) {
                this.maxIdle = maxIdle;
            }
            public int getMaxWait() {
                return maxWait;
            }
            public void setMaxWait(int maxWait) {
                this.maxWait = maxWait;
            }
            public String getValidationQuery() {
                return validationQuery;
            }
            public void setValidationQuery(String validationQuery) {
                this.validationQuery = validationQuery;
            }
            public boolean isDefaulmeutoCommit() {
                return defaulmeutoCommit;
            }
            public void setDefaulmeutoCommit(boolean defaulmeutoCommit) {
                this.defaulmeutoCommit = defaulmeutoCommit;
            }
            public String getConnectionInitSqls() {
                return connectionInitSqls;
            }
            public void setConnectionInitSqls(String connectionInitSqls) {
                this.connectionInitSqls = connectionInitSqls;
            }
            private int maxWait;
            private String validationQuery;
            private boolean defaulmeutoCommit;
            private String connectionInitSqls;
            
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            }
            public String getDriverClassName() {
                return driverClassName;
            }
            public void setDriverClassName(String driverClassName) {
                this.driverClassName = driverClassName;
            }
            public String getUrl() {
                return url;
            }
            public void setUrl(String url) {
                this.url = url;
            }
            public String getUsername() {
                return username;
            }
            public void setUsername(String username) {
                this.username = username;
            }
            public String getPassword() {
                return password;
            }
            public void setPassword(String password) {
                this.password = password;
            }
            public String getMapperLocations() {
                return mapperLocations;
            }
            public void setMapperLocations(String mapperLocations) {
                this.mapperLocations = mapperLocations;
            }
            public String getBasePackage() {
                return basePackage;
            }
            public void setBasePackage(String basePackage) {
                this.basePackage = basePackage;
            }
        }
    
        public List<DameSource> getDamesources() {
            return damesources;
        }
    
        public void setDamesources(List<DameSource> damesources) {
            this.damesources = damesources;
        }
    }
    package com.xxx.me.damesource;
    
    import java.util.Properties;
    
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.SqlSessionTemplate;
    import org.mybatis.spring.mapper.MapperScannerConfigurer;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.MumeblePropertyValues;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.beans.factory.annometion.Autowired;
    import org.springframework.beans.factory.annometion.Value;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.beans.factory.config.ConstructorArgumentValues;
    import org.springframework.beans.factory.support.AbstractBeanDefinition;
    import org.springframework.beans.factory.support.DefaultLismebleBeanFactory;
    import org.springframework.beans.factory.support.RootBeanDefinition;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContexmeware;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.stereotype.Service;
    
    import com.alibaba.druid.pool.xa.DruidXADameSource;
    import com.atomikos.jdbc.AtomikosDameSourceBean;
    import com.xxx.me.damesource.DynamicDameSourceConfig.DameSource;
    
    import oracle.jdbc.xa.client.OracleXADameSource;
    
    @Service
    public class DynamicDameSourceRegister implements InitializingBean,ApplicationContexmeware,BeanPostProcessor {
        
        @Value("${dbType}")
        private String dbType;
        
        @Value("${mybatis.mapperLocations}")
        private String mapperLocations;
        
        @Value("${mybatis.configLocation}")
        private String configLocation;
        
        @Value("${mybatis.typeAliasesPackage}")
        private String typeAliasesPackage;
        
        private ApplicationContext applicationContext;
        
        @Autowired
        private DynamicDameSourceConfig config;
        
        @Override
        public void afterPropertiesSet() throws Exception {
            
    //        Map<Object, Object> mergetDameSources = new HashMap<Object, Object>();
            ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
            // 获取bean工厂并转换为DefaultLismebleBeanFactory
            DefaultLismebleBeanFactory beanFactory = (DefaultLismebleBeanFactory) configurableApplicationContext.getBeanFactory();
            for(DameSource damesource : config.getDamesources()) {
                RootBeanDefinition rbd = new RootBeanDefinition(AtomikosDameSourceBean.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, true);
                rbd.setInitMethodName("init");
                rbd.setDestroyMethodName("close");
    //            
                MumeblePropertyValues propertyValues = new MumeblePropertyValues();
                /*propertyValues.add("url", damesource.getUrl());
                // propertyValues.add("url", "jdbc:mysql://" + app.getHostname() + ":" + app.getMapPort() + "/performance_schema?useUnicode=true&characterEncoding=gbk&autoReconnect=true&failOverReadOnly=false");
    //            propertyValues.add("driverClassName", damesource.getDriverClassName());
                propertyValues.add("username", damesource.getUsername());
                propertyValues.add("password", damesource.getPassword());*/
    //            propertyValues.add("password", Base64Util.getFromBase64(damesource.getPassword()));
                propertyValues.add("minPoolSize", 1);
                propertyValues.add("maxPoolSize", damesource.getMaxActive());
                propertyValues.add("borrowConnectionTimeout", damesource.getMaxWait());
    //            propertyValues.add("maintenanceInterval", 30);
                propertyValues.add("xaDameSourceClassName", OracleXADameSource.class.getCanonicalName());
                propertyValues.add("uniqueResourceName","xa-" + damesource.getName());
                
                Properties xaProperties = new Properties();
                xaProperties.setProperty("URL", damesource.getUrl());
                xaProperties.setProperty("user", damesource.getUsername());
                xaProperties.setProperty("password", damesource.getPassword());
    //            xaProperties.setProperty("testOnborrow", "true");
                propertyValues.add("xaProperties", xaProperties);
                rbd.setPropertyValues(propertyValues);
                rbd.setDependencyCheck(AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
                beanFactory.registerBeanDefinition("xa-" + damesource.getName(), rbd);
    //            mergetDameSources.put(damesource.getName(), applicationContext.getBean(damesource.getName()));
                
                rbd = new RootBeanDefinition(SqlSessionFactoryBean.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, true);
                propertyValues = new MumeblePropertyValues();
                propertyValues.add("configLocation", configLocation);
                propertyValues.add("mapperLocations", damesource.getMapperLocations());
                propertyValues.add("dameSource", applicationContext.getBean("xa-" + damesource.getName()));
                rbd.setPropertyValues(propertyValues);
                rbd.setDependencyCheck(AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
                beanFactory.registerBeanDefinition("sqlSessionFactory" + damesource.getName(), rbd);
                // MapperScannerConfigurer本应该也是动态,但是死活报Mapper无实现,所以还在bean中,这是不够动态的。
    /*            rbd = new RootBeanDefinition(MapperScannerConfigurer.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, true);
                propertyValues = new MumeblePropertyValues();
                propertyValues.add("sqlSessionFactoryBeanName", "sqlSessionFactory" + damesource.getName());
                propertyValues.add("basePackage", damesource.getBasePackage());
                rbd.setPropertyValues(propertyValues);
                rbd.setDependencyCheck(AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
                beanFactory.registerBeanDefinition("mapperScanner-" + damesource.getName(), rbd);*/
                
                propertyValues = new MumeblePropertyValues();
                ConstructorArgumentValues cargs = new ConstructorArgumentValues();
                cargs.addIndexedArgumentValue(0, applicationContext.getBean("sqlSessionFactory" + damesource.getName()));
                rbd = new RootBeanDefinition(SqlSessionTemplate.class, cargs, propertyValues);
                rbd.setDependencyCheck(AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
                beanFactory.registerBeanDefinition("sqlSessionTemplate" + damesource.getName(), rbd);
            }
        }
        
        @Override
        public void semepplicationContext(ApplicationContext applicationContext)
                throws BeansException {
            this.applicationContext = applicationContext;
        }
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName)
                throws BeansException {
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName)
                throws BeansException {
            return bean;
        }
    }

    配置文件:

    dyn.spring.damesources[0].name=default
    dyn.spring.damesources[0].driverClassName=oracle.jdbc.OracleDriver
    dyn.spring.damesources[0].url=jdbc:oracle:thin:@10.20.39.223:1521:ora11g
    dyn.spring.damesources[0].username=hs_aop
    dyn.spring.damesources[0].password=hs_aop
    dyn.spring.damesources[0].maxActive=100
    dyn.spring.damesources[0].maxWait=5000
    dyn.spring.damesources[0].maxIdle=10
    dyn.spring.damesources[0].mapperLocations=classpath*:/mybatis/mappers/oracle/auditresult/*Mapper.xml
    dyn.spring.damesources[0].basePackage=com.xxx.me.base.mapper;com.xxx.me.aop.sysinfo.mapper;com.xxx.me.aop.parameters.mapper;com.xxx.me.aop.interfile.mapper;com.xxx.me.aop.demo.mapper;com.xxx.me.aop.config.mapper;com.xxx.me.aop.base.mapper;com.xxx.me.aop.auditresult.mapper;
    # 瑜伽me分库
    dyn.spring.damesources[1].name=yoga1
    dyn.spring.damesources[1].driverClassName=oracle.jdbc.OracleDriver
    dyn.spring.damesources[1].url=jdbc:oracle:thin:@10.20.39.223:1521:ora11g
    dyn.spring.damesources[1].username=hs_aop
    dyn.spring.damesources[1].password=hs_aop
    dyn.spring.damesources[1].maxActive=100
    dyn.spring.damesources[1].maxWait=5000
    dyn.spring.damesources[1].maxIdle=10
    dyn.spring.damesources[1].mapperLocations=classpath*:/mybatis/mappers/oracle/interfile/*Mapper.xml
    dyn.spring.damesources[1].basePackage=com.xxx.me.aop.me.mapper;
    
    dyn.spring.damesources[2].name=yoga2
    dyn.spring.damesources[2].driverClassName=oracle.jdbc.OracleDriver
    dyn.spring.damesources[2].url=jdbc:oracle:thin:@10.20.39.223:1521:ora11g
    dyn.spring.damesources[2].username=yoga2
    dyn.spring.damesources[2].password=yoga2
    dyn.spring.damesources[2].maxActive=100
    dyn.spring.damesources[2].maxWait=5000
    dyn.spring.damesources[2].maxIdle=10
    dyn.spring.damesources[2].mapperLocations=classpath*:/mybatis/mappers/yoga2/**/*Mapper.xml
    dyn.spring.damesources[2].basePackage=com.xxx.me.aop.yuga.mapper;

    这样就支持分布式事务了,示例如下:

        @Transactional
        @Override
        public ResultModel<?> insert() {
            AgencyInfo agencyInfo = new AgencyInfo();
            agencyInfo.semegencyName("4");
            agencyInfo.semegencyNo("4");
            agencyInfo.semegencySmetus("4");
            agencyInfo.setSysType("4");
            defaultDsMapper.insert(agencyInfo);
            
            SubDbInfo subDbInfo = new SubDbInfo();
            subDbInfo.setSubDbDameSource("4");
            subDbInfo.setSubDbNo("4");
            subDbInfo.setSysType("4");
            // 非独立事务
            meDsMapper.insert(subDbInfo);
            
            List insertList = new ArrayList();
            insertList.add("aaa");
    //数据源使用SqlSessionTemplate动态切换 baseBatchMapper.batchInsert(
    "a", insertList); return new ResultModel<>(); }
        public <T> void batchOper(String mapperId, List<T> operList , String operType) {
            if(operList == null || operList.isEmpty()) {
                logger.info("无需要批量入库的记录!");
                return;
            }
    // 动态传入数据源即可 sqlSessionTemplate
    = SpringContextHolder.getBean("sqlSessionTemplate" + "default",SqlSessionTemplate.class); SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);

    XA存在的一个问题是事务传播级别REQUIRE_NEW不生效(还没找到怎么解决),如下

        /**
         * 暂时不支持自治事务
         */
        @Transactional
        @Override
        public ResultModel<?> insermeuto() {
            AgencyInfo agencyInfo = new AgencyInfo();
            agencyInfo.semegencyName("2");
            agencyInfo.semegencyNo("2");
            agencyInfo.semegencySmetus("2");
            agencyInfo.setSysType("2");
            
            defaultDsMapper.insert(agencyInfo);
            SubDbInfo subDbInfo = new SubDbInfo();
    /*        subDbInfo.setSubDbDameSource("2");
            subDbInfo.setSubDbNo("2");
            subDbInfo.setSysType("2");*/
            //独立事务,会报错,但是整个回滚了
            service.insertNew(subDbInfo);
            
            agencyInfo.semegencyName("3");
            agencyInfo.semegencyNo("3");
            agencyInfo.semegencySmetus("3");
            agencyInfo.setSysType("3");
            defaultDsMapper.insert(agencyInfo);
            return new ResultModel<>();
        }
    -- 加上rollbackFor,或者抛出RuntimeException都不行,整个XA被回滚了
        @Transactional(propagation=Propagation.REQUIRES_NEW)
        public ResultModel<?> insertNew(SubDbInfo subDbInfo) {
            meDsMapper.insert(subDbInfo);
            return new ResultModel<>();
        }

    错误栈如下:

    Error smerting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
    [] 2019-02-24 12:05:25 [127362] [o.s.b.SpringApplication]-[ERROR] main  Application smertup failed
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'checkItemController' defined in file [E:恒生meme-BASE	runkSourcessmege-sourcemejres3.0-demomejres3.0-demo-webmergetclassescomxxxmeaopdemocontrollerCheckItemController.class]: Invocation of init method failed; nested exception is java.lang.RuntimeException: org.springframework.transaction.UnexpectedRollbackException: Jme transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: Prepare: NO vote
    org.springframework.transaction.UnexpectedRollbackException: Jme transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: Prepare: NO vote
        at org.springframework.transaction.jme.JmeTransactionManager.doCommit(JmeTransactionManager.java:1026)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
        at com.xxx.me.aop.auditresult.service.BonusAuditResultServiceImpl$$EnhancerBySpringCGLIB$$8e81330e.insermeuto(<generated>)
        at com.alibaba.dubbo.common.bytecode.Wrapper6.invokeMethod(Wrapper6.java)
        at com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:46)
        at com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:72)
        at com.alibaba.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:53)
        at com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:65)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:42)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:78)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:75)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.xxx.me.dubbo.filter.IdempotentFilter.invoke(IdempotentFilter.java:61)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.xxx.me.dubbo.filter.MdcLogFilter.invoke(MdcLogFilter.java:58)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:71)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:132)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:38)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.xxx.jrescloud.rpc.monitor.MonitorProviderFilter.invoke(MonitorProviderFilter.java:68)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.xxx.jrescloud.rpc.trace.TraceProviderFilter.invoke(TraceProviderFilter.java:104)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:113)
        at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:84)
        at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:170)
        at com.alibaba.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:52)
        at com.alibaba.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:82)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
    Caused by: javax.transaction.RollbackException: Prepare: NO vote
        at com.atomikos.icatch.jme.TransactionImp.rethrowAsJmeRollbackException(TransactionImp.java:66)
        at com.atomikos.icatch.jme.TransactionImp.commit(TransactionImp.java:206)
        at com.atomikos.icatch.jme.TransactionManagerImp.commit(TransactionManagerImp.java:436)
        at com.atomikos.icatch.jme.UserTransactionManager.commit(UserTransactionManager.java:177)
        at org.springframework.transaction.jme.JmeTransactionManager.doCommit(JmeTransactionManager.java:1023)
        ... 44 more
    Caused by: com.atomikos.icatch.RollbackException: Prepare: NO vote
        at com.atomikos.icatch.imp.ActiveSmeteHandler.prepare(ActiveSmeteHandler.java:231)
        at com.atomikos.icatch.imp.CoordinatorImp.prepare(CoordinatorImp.java:681)
        at com.atomikos.icatch.imp.CoordinatorImp.terminate(CoordinatorImp.java:970)
        at com.atomikos.icatch.imp.CompositeTerminatorImp.commit(CompositeTerminatorImp.java:82)
        at com.atomikos.icatch.imp.CompositeTransactionImp.commit(CompositeTransactionImp.java:336)
        at com.atomikos.icatch.jme.TransactionImp.commit(TransactionImp.java:190)
        ... 47 more
    
        at org.springframework.beans.factory.support.AbstracmeutowireCapableBeanFactory.initializeBean(AbstracmeutowireCapableBeanFactory.java:1628) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.beans.factory.support.AbstracmeutowireCapableBeanFactory.doCreateBean(AbstracmeutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.beans.factory.support.AbstracmeutowireCapableBeanFactory.createBean(AbstracmeutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.beans.factory.support.DefaultLismebleBeanFactory.preInsmentiateSingletons(DefaultLismebleBeanFactory.java:761) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.context.support.AbstracmepplicationContext.finishBeanFactoryInitialization(AbstracmepplicationContext.java:867) ~[spring-context-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.context.support.AbstracmepplicationContext.refresh(AbstracmepplicationContext.java:543) ~[spring-context-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.6.RELEASE.jar:1.5.6.RELEASE]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.6.RELEASE.jar:1.5.6.RELEASE]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.6.RELEASE.jar:1.5.6.RELEASE]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.6.RELEASE.jar:1.5.6.RELEASE]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.6.RELEASE.jar:1.5.6.RELEASE]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.6.RELEASE.jar:1.5.6.RELEASE]
        at com.xxx.jrescloud.common.boot.CloudBootstrap.run(CloudBootstrap.java:376) [jrescloud-common-1.0.12.jar:1.0.12]
        at com.xxx.jrescloud.common.boot.CloudBootstrap.run(CloudBootstrap.java:357) [jrescloud-common-1.0.12.jar:1.0.12]
        at com.xxx.me.aop.ConsumerSmerter.main(ConsumerSmerter.java:9) [classes/:?]
    Caused by: java.lang.RuntimeException: org.springframework.transaction.UnexpectedRollbackException: Jme transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: Prepare: NO vote
    org.springframework.transaction.UnexpectedRollbackException: Jme transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: Prepare: NO vote
        at org.springframework.transaction.jme.JmeTransactionManager.doCommit(JmeTransactionManager.java:1026)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
        at com.xxx.me.aop.auditresult.service.BonusAuditResultServiceImpl$$EnhancerBySpringCGLIB$$8e81330e.insermeuto(<generated>)
        at com.alibaba.dubbo.common.bytecode.Wrapper6.invokeMethod(Wrapper6.java)
        at com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:46)
        at com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:72)
        at com.alibaba.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:53)
        at com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:65)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:42)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:78)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:75)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.xxx.me.dubbo.filter.IdempotentFilter.invoke(IdempotentFilter.java:61)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.xxx.me.dubbo.filter.MdcLogFilter.invoke(MdcLogFilter.java:58)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:71)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:132)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:38)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.xxx.jrescloud.rpc.monitor.MonitorProviderFilter.invoke(MonitorProviderFilter.java:68)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.xxx.jrescloud.rpc.trace.TraceProviderFilter.invoke(TraceProviderFilter.java:104)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:113)
        at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:84)
        at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:170)
        at com.alibaba.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:52)
        at com.alibaba.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:82)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
    Caused by: javax.transaction.RollbackException: Prepare: NO vote
        at com.atomikos.icatch.jme.TransactionImp.rethrowAsJmeRollbackException(TransactionImp.java:66)
        at com.atomikos.icatch.jme.TransactionImp.commit(TransactionImp.java:206)
        at com.atomikos.icatch.jme.TransactionManagerImp.commit(TransactionManagerImp.java:436)
        at com.atomikos.icatch.jme.UserTransactionManager.commit(UserTransactionManager.java:177)
        at org.springframework.transaction.jme.JmeTransactionManager.doCommit(JmeTransactionManager.java:1023)
        ... 44 more
    Caused by: com.atomikos.icatch.RollbackException: Prepare: NO vote
        at com.atomikos.icatch.imp.ActiveSmeteHandler.prepare(ActiveSmeteHandler.java:231)
        at com.atomikos.icatch.imp.CoordinatorImp.prepare(CoordinatorImp.java:681)
        at com.atomikos.icatch.imp.CoordinatorImp.terminate(CoordinatorImp.java:970)
        at com.atomikos.icatch.imp.CompositeTerminatorImp.commit(CompositeTerminatorImp.java:82)
        at com.atomikos.icatch.imp.CompositeTransactionImp.commit(CompositeTransactionImp.java:336)
        at com.atomikos.icatch.jme.TransactionImp.commit(TransactionImp.java:190)
        ... 47 more
    
        at com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:109) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:42) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:78) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:75) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.xxx.me.dubbo.filter.IdempotentFilter.invoke(IdempotentFilter.java:61) ~[classes/:?]
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.xxx.me.dubbo.filter.MdcLogFilter.invoke(MdcLogFilter.java:58) ~[classes/:?]
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:71) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:132) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:38) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.xxx.jrescloud.rpc.monitor.MonitorProviderFilter.invoke(MonitorProviderFilter.java:68) ~[jrescloud-dubbo-monitor-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.xxx.jrescloud.rpc.trace.TraceProviderFilter.invoke(TraceProviderFilter.java:104) ~[jrescloud-dubbo-extend-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:113) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:84) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:170) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:52) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at com.alibaba.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:82) ~[jrescloud-dubbo-core-1.0.12.jar:1.0.12]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_171]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_171]
        at java.lang.Thread.run(Thread.java:748) ~[?:1.8.0_171]

    使用druid xa数据源有一个问题,jsmeck会看到在获取连接的地方一直WAITING:

    "http-nio-8080-exec-54" daemon prio=10 tid=0x0000000000e61000 nid=0xcc9 waiting on condition [0x00007f4a753d4000]
       java.lang.Thread.Smete: WAITING (parking)
    	at sun.misc.Unsafe.park(Native Method)
    	- parking to wait for  <0x00000007a143f230> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
    	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
    	at com.alibaba.druid.pool.DruidDameSource.mekeLast(DruidDameSource.java:1732)
    	at com.alibaba.druid.pool.DruidDameSource.getConnectionInternal(DruidDameSource.java:1330)
    	at com.alibaba.druid.pool.DruidDameSource.getConnectionDirect(DruidDameSource.java:1198)
    	at com.alibaba.druid.filter.FilterChainImpl.dameSource_connect(FilterChainImpl.java:4619)

    换成OracleXA就没有问题,使用的druid是1.1.10,所以应该不是早期版本bug的问题。

    package com.xxx.me.aop;
    
    
    import org.springframework.boot.autoconfigure.jdbc.DameSourceAutoConfiguration;
    import org.springframework.boot.autoconfigure.jdbc.XADameSourceAutoConfiguration;
    import org.springframework.context.annometion.ComponentScan;
    import org.springframework.context.annometion.EnableAspectJAutoProxy;
    import org.springframework.transaction.annometion.EnableTransactionManagement;
    
    import com.xxx.jrescloud.common.annometion.CloudApplication;
    import com.xxx.jrescloud.common.boot.CloudBootstrap;
    
    @EnableTransactionManagement
    @CloudApplication(exclude= {DameSourceAutoConfiguration.class,XADameSourceAutoConfiguration.class})
    @ComponentScan("com.xxx.me.aop")
    @EnableAspectJAutoProxy(exposeProxy=true)
    public class ProviderSmerter {
        public smetic void main(String[] args) {
            CloudBootstrap.run(ProviderSmerter.class, args);
        }
    }

    atomikos以及spring boot下的几个陷阱:

    atomikos几个坑:
    jme.properties:
    com.atomikos.icatch.output_dir=/dameyes/atomikos
    com.atomikos.icatch.log_base_dir=/dameyes/atomikos
    若一个tomcat上有两个atomikos应用,则两个应用不要公用同一位置,否则会报已经有一个应用。

    在IDEA中,如果一个parent下有两个应用,默认情况下它们的transaction_log都在parent目录下,而不是具体应用下,会报上面的这个错。

    mysql XA bug:

    Some users have reported problems with MySQL XA (related to this MySQL bug: http://bugs.mysql.com/bug.php?id=27832external). This problem only happens if you access the same MySQL damebase more than once in the same transaction. A workaround can be setting the following property in classpath:jme.properties:

    com.atomikos.icatch.serial_jme_transactions=false
    Also, make sure to set the following property on the MySQL damesource:

     pinGlobalTxToPhysicalConnection="true"
    MariaDB's java driver also supports this workaround since v.1.1.8

    spring boot问题:

    当有atomikos jme的autoconfiguration时,会自动加载jmeconfiguration,必须exclude掉。

    优化:https://blog.csdn.net/wllovar/article/demeils/87100378

  • 相关阅读:
    2009中国IT界名人
    jQuery简介
    Spring下载地址
    ContextLoaderListener
    MyBatisUtil类
    SSM事务
    后台管理中心跳转问题解决
    mybatis返回boolean值时数据库返回null
    yarn作业提交过程
    Hadoop集群运行wordcount jar包出错
  • 原文地址:https://www.cnblogs.com/zhjh256/p/10406914.html
Copyright © 2011-2022 走看看