建立一個項目Tm 項目
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL4YjN1UDOzkDMxETNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
導包pom
<!-- 參照例子引入需要的依賴jar -->
<dependency>
<groupId>com.codingapi.txlcn</groupId>
<artifactId>txlcn-tm</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
注意 jdbc 包必須依賴 不然啟動報錯
配置檔案
spring.application.name=txlcn-tm
server.port=7970
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/tx-manager?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto=update
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.use-generated-keys=true
# TM背景登陸密碼
tx-lcn.manager.admin-key=123456
tx-lcn.manager.host=127.0.0.1
tx-lcn.manager.port=8070
# 開啟日志,預設為false
tx-lcn.logger.enabled=true
tx-lcn.logger.driver-class-name=${spring.datasource.driver-class-name}
tx-lcn.logger.jdbc-url=${spring.datasource.url}
tx-lcn.logger.username=${spring.datasource.username}
tx-lcn.logger.password=${spring.datasource.password}
logging.level.com.codingapi.txlcn=DEBUG
#redis 主機
spring.redis.host=127.0.0.1
#redis 端口
spring.redis.port=6379
#redis 密碼
spring.redis.password=123456
啟動類注解
import com.codingapi.txlcn.tm.config.EnableTransactionManagerServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Created by IntelliJ IDEA.
*
* @Author : WangCong
* @create 2020/5/9 15:23
*/
@SpringBootApplication
@EnableTransactionManagerServer
public class TxLcnTmApplication {
public static void main(String[] args) {
SpringApplication.run(TxLcnTmApplication.class,args);
}
}
建立資料庫表
然後建立表
CREATE TABLE `t_tx_exception` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`group_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`unit_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`mod_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`transaction_state` tinyint(4) NULL DEFAULT NULL,
`registrar` tinyint(4) NULL DEFAULT NULL,
`remark` varchar(4096) NULL DEFAULT NULL,
`ex_state` tinyint(4) NULL DEFAULT NULL COMMENT '0 未解決 1已解決',
`create_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
這個Tm 服務就弄好了,啟動。
在其他 要用到分布式事務的項目 中 引入包
比如我 一個提供者 項目和一個消費者項目 都要引入
這是提供者的pom
<dependency>
<groupId>com.codingapi.txlcn</groupId>
<artifactId>txlcn-tc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.codingapi.txlcn</groupId>
<artifactId>txlcn-txmsg-netty</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
啟動類
/**
* Created by IntelliJ IDEA.
*
* @Author : WangCong
* @create 2020/5/7 15:26
*/
//注冊服務到注冊中心去
@EnableDiscoveryClient
@SpringBootApplication
@EnableBinding(MessageService.class)
//開啟分布式事務
@EnableDistributedTransaction
@EnableTransactionManagement
public class ProviderRun {
public static void main(String[] args) {
SpringApplication.run(ProviderRun.class, args);
}
}
服務代碼
@Service
public class SysServiceImpl implements SysService {
@Autowired
private SysUserMapper sysUserMapper;
/**
* @LcnTransaction//分布式事務
* @Transactional //本地事務
* @param sysUser
* @return
*/
@Override
@LcnTransaction(propagation = DTXPropagation.SUPPORTS)
@Transactional
public int add(SysUser sysUser) {
String groupId = TracingContext.tracing().groupId();
String applicationId = Transactions.getApplicationId();
System.out.println(groupId);
System.out.println(applicationId);
return sysUserMapper.add(sysUser);
}
}
關于DTXPropagation源碼裡面有解釋
/**
* 目前沒有分布式事務,就建立。目前有分布式事務,就加入
*/
REQUIRED,
/**
* 目前沒有分布式事務,非分布式事務運作。目前有分布式事務,就加入
*/
SUPPORTS;
是以一般事物發起方使用REQUIRED,事物參與方使用SUPPORTS
這裡因為 我是在消費者項目中調用的提供者的服務 ,這裡的是 事物參與方 使用SUPPORTS
配置檔案
server:
port: 8081
spring:
profiles:
include: dev
application:
name: provider1
eureka:
client:
serviceUrl:
defaultZone: http://eurka-server2-8060:8060/eureka/,http://eurka-server1-8080:8080/eureka/
instance:
#eureka伺服器在接收到最後一個心跳之後等待的時間,然後才能從清單中删除此執行個體 預設90s(開發環境)
lease-expiration-duration-in-seconds: 10
#eureka用戶端需要向eureka伺服器發送心跳的頻率 預設30s (開發環境)
lease-renewal-interval-in-seconds: 1
instance-id: ${spring.cloud.client.ip-address}:${server.port}
preferIpAddress: true
tx-lcn:
client:
manager-address: 127.0.0.1:8070
springcloud:
loadbalance:
enabled: true
微服務叢集且用到 LCN事務模式時,為保證性能請開啟TX-LCN重寫的負載政策
tx-lcn.springcloud.loadbalance.enabled=true
消費者的pom
<dependency>
<groupId>com.codingapi.txlcn</groupId>
<artifactId>txlcn-tc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.codingapi.txlcn</groupId>
<artifactId>txlcn-txmsg-netty</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
啟動類
import com.codingapi.txlcn.tc.config.EnableDistributedTransaction;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* Created by IntelliJ IDEA.
* 注解@SpringCloudApplication包括:@SpringBootApplication、@EnableDiscoveryClient、@EnableCircuitBreaker,分别是SpringBoot注解、注冊服務中心Eureka注解、斷路器注解
* @Author : WangCong
* @create 2020/5/9 9:47
*/
@SpringCloudApplication
@EnableFeignClients
//開啟分布式事務
@EnableDistributedTransaction
@EnableTransactionManagement
public class FeignApplication {
public static void main(String[] args) {
SpringApplication.run(FeignApplication.class,args);
}
}
配置檔案
server:
port: 8084
spring:
profiles:
include: dev
application:
name: feign1
eureka:
client:
serviceUrl:
defaultZone: http://eurka-server2-8060:8060/eureka/,http://eurka-server1-8080:8080/eureka/
#healthcheck:
enabled: true #開啟自定義健康檢查
instance:
#eureka伺服器在接收到最後一個心跳之後等待的時間,然後才能從清單中删除此執行個體 預設90s(開發環境)
lease-expiration-duration-in-seconds: 10
#eureka用戶端需要向eureka伺服器發送心跳的頻率 預設30s (開發環境)
lease-renewal-interval-in-seconds: 1
instance-id: ${spring.cloud.client.ip-address}:${server.port}
preferIpAddress: true
#開啟hystrix 熔斷
feign:
hystrix:
enabled: true
tx-lcn:
client:
manager-address: 127.0.0.1:8070
springcloud:
loadbalance:
enabled: true
調用提供者代碼
@RequestMapping("/add")
@Transactional
@LcnTransaction
public String test2(){
String groupId = TracingContext.tracing().groupId();
String applicationId = Transactions.getApplicationId();
System.out.println(groupId);
System.out.println(applicationId);
SysUser user = new SysUser();
user.setCreateTime(new Date());
user.setPassword("123");
user.setUsername("asdasd");
user.setSalt("asas");
user.setStatus(0);
helloService.list(user);
user.setUsername("xixixi");
List list=new ArrayList();
System.out.println(list.get(23));
int add = sysUserMapper.add(user);
return add+"";
}
這裡我使用的是feign 的遠端調用方式
/**
* Created by IntelliJ IDEA.
*
* @Author : WangCong
* @create 2020/5/9 9:58
*/
/**
* 遠端服務名稱 可以大小寫
*/
@FeignClient(value = "provider1",fallbackFactory = TestFeignFallbackFactory.class)
public interface HelloService {
@RequestMapping("/service/hello")
public String hello();
@RequestMapping("/service/hello1")
public String hello1();
@RequestMapping("/list")
public String list(@RequestBody SysUser user);
}
是以在熔斷的配置注意
熔斷配置
import com.codingapi.txlcn.tc.support.DTXUserControls;
import com.codingapi.txlcn.tracing.TracingContext;
import com.wc.springcloud.model.SysUser;
import com.wc.springcloud.service.HelloService;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
/**
* Created by IntelliJ IDEA.
*
* @Author : WangCong
* @create 2020/5/9 10:26
*/
@Component
public class TestFeignFallbackFactory implements FallbackFactory<HelloService> {
@Override
public HelloService create(Throwable throwable) {
return new HelloService() {
@Override
public String hello() {
return throwable.getMessage();
}
@Override
public String hello1() {
return throwable.getMessage();
}
@Override
public String list(SysUser user) {
//復原事務
DTXUserControls.rollbackGroup(TracingContext.tracing().groupId());
return throwable.getMessage();
}
};
}
}
注意這句話DTXUserControls.rollbackGroup(TracingContext.tracing().groupId());
如果沒有配置,出現異常 事務不會復原。
運作測試
提供者代碼異常
檢視資料庫 事務復原
注意
我之前代碼 提供者 和消費者
提供者列印輸出的是
消費者列印輸出的是
第一個是組id,第二個是 每個服務的應用辨別
兩邊的組id 都是一樣的。
如果不一樣,你配置的有問題