概述
Beast-tx是一個輕量級不侵入業務代碼的TCC分佈式事務框架。支持dubbo和spring cloud。
特性
- 支持主流的RPC框架:dubbo和spring cloud
- 配置簡單。不侵入業務代碼
- 提供一個事務信息收集器,可以自行擴展。
- 幾乎沒有性能損耗。
2. Beast-tx For Dubbo
2.1 如果你使用spring
在你的項目中加上依賴,maven的GAV為:
<code><dependency>
<groupid>com.thebeastshop/<groupid>
<artifactid>beast-tx-dubbo/<artifactid>
<version>${version}/<version>
/<dependency>/<code>
目前中央倉庫沒有上傳,需要自己編譯打包
然後在dubbo的消費者端的applicationContext.xml裡配置如下:
<code><aspectj-autoproxy>
<bean>
<bean>/<code>
2.2 如果你使用springboot
在你的項目中加上依賴,maven的GAV為:
<code> <dependency>
<groupid>com.thebeastshop/<groupid>
<artifactid>beast-tx-dubbo-spring-boot-starter/<artifactid>
<version>${version}/<version>
/<dependency>/<code>
目前中央倉庫沒有上傳,需要自己編譯打包
由於對springboot作了自動裝配,因此只需引入包即可。不用額外配置
2.3 使用方法
假設你的dubbo提供者端有一個service:DemoService,接口定義如下:
<code>String test1(String name);
String test2(String name, Integer age);
String test3(Long id);/<code>
假設test方法需要支持分佈式TCC事務,則需要遵循以下約定:
- 定義並實現tryTest(String name)方法,主要用於校驗一些前置條件,如參數合法性,業務的前置判斷等。參數必須和主體方法參數一致,但這不是必須的,如果您的前置判斷寫在test方法主體裡,那這個方法可以不定義。
- 定義並實現cancelTest(String str)方法,用於做業務的回滾操作。如果在回滾方法裡需要用到方法主體返回的結果,也可以定義為cancelTest(String str, Object result)。BeastTx對這2種定義都支持。
然後在你的dubbo消費者端需要加入分佈式事務的service中的method上加上@BeastTx標籤即可
完整例子如下:
dubbo提供者端
<code>public interface DemoService {
boolean tryTest1(String name);
String test1(String name);
String test2(String name, Integer age);
String test3(Long id);
void cancelTest1(String str);
void cancelTest2(String str);
}/<code>
dubbo消費者端
<code>@Service("testService")
public class TestServiceImpl implements TestService {
private final static Logger log = LoggerFactory.getLogger(TestServiceImpl.class);
@Resource
private DemoService demoService;//這是另外一個服務的service
@Resource
private JdbcTemplate jdbcTemplate;
@Override
@BeastTx
public void consumerTest() {
jdbcTemplate.execute("insert into user (name, age) values ('beast-tx', '99131')");
String result = demoService.test1("jack");
log.info("result:" + result);
demoService.test3(8L);
}
}/<code>
以上示例為一個本地事務+dubbo遠程事務test1+dubbo遠程事務test3,假設dubboService.test3出錯。那整個執行順序如下:
- 先執行本地事務jdbcTemplate.execute("insert into user (name, age) values ('beast-tx', '99131')")
- 自動執行demoService.tryTest1(String name)進行業務前置判斷檢查
- 執行demoService.test1(String name)進行業務操作
- 執行demoService.test3(Long id)進行業務操作,拋出錯誤
- 自動執行demoService.cancelTest3(Long id)進行回滾操作
- 本地事務的回滾操作
3.Beast-tx For Spring Cloud
3.1 依賴和配置
在你的項目中加上依賴,maven的GAV為:
<code><dependency>
<groupid>com.thebeastshop/<groupid>
<artifactid>beast-tx-feign-spring-boot-starter/<artifactid>
<version>${version}/<version>
/<dependency>/<code>
目前中央倉庫沒有上傳,需要自己編譯打包
springboot會自動裝配,如無其他配置
3.2 使用方法
對Spring Cloud的Feign提供支持。所需要用的方法約束,和2.3類似,不再重複
下面只貼出例子:
Feign的提供者端:
<code>@RestController
public class ProviderController {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private ProviderDomain providerDomain;
@RequestMapping("/hi")
public String sayHello(@RequestParam String name){
System.out.println("invoke method hi,name="+name);
String services = "Services:" + discoveryClient.getServices();
System.out.println(services);
return "hello," + name;
}
@RequestMapping("/tryTest1")
public boolean tryTest1(@RequestParam String name){
log.info("invoked tryTest1");
return providerDomain.tryTest1(name);
}
@RequestMapping("/test1")
public String test1(@RequestParam String name){
log.info("invoked test1");
return providerDomain.test1(name);
}
@RequestMapping("/cancelTest1")
public void cancelTest1(@RequestParam String name){
log.info("invoked cancelTest1");
providerDomain.cancelTest1(name);
}
public String test2(@RequestParam String name){
return providerDomain.test2(name);
}
}/<code>
Feign的消費者端
Feign接口定義:
<code>@FeignClient("test-provider")
public interface TxTestSayhiFeignClient {
@RequestMapping(value = "hi",method = RequestMethod.GET)
public String sayHello(@RequestParam(value = "name") String name);
@RequestMapping(value = "tryTest1",method = RequestMethod.GET)
public boolean tryTest1(@RequestParam(value = "name") String name);
@RequestMapping(value = "test1",method = RequestMethod.GET)
public String test1(@RequestParam(value = "name") String name);
@RequestMapping(value = "cancelTest1",method = RequestMethod.GET)
public void cancelTest1(@RequestParam(value ="name") String name);
@RequestMapping(value = "test2",method = RequestMethod.GET)
public String test2(@RequestParam(value = "name") String name);
}/<code>
消費者實現類:
<code>@Component
public class ConsumerDomain {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private TxTestSayhiFeignClient txTestSayhiFeignClient;
@BeastTx
public String doTest(String name){
jdbcTemplate.execute("insert into user (name, age) values ('beast-tx', '99131')");
String result = txTestSayhiFeignClient.test1("jack");
System.out.println("result:" + result);
txTestSayhiFeignClient.test2("rose");
return "ok";
}
}/<code>
以上示例為一個本地事務+Feign遠程事務test1+Feign遠程事務test2,假設txTestSayhiFeignClient.test2出錯。那整個執行順序如下:
- 先執行本地事務jdbcTemplate.execute("insert into user (name, age) values ('beast-tx', '99131')")
- 自動執行txTestSayhiFeignClient.tryTest1(String name)進行業務前置判斷檢查
- 執行txTestSayhiFeignClient.test1(String name)進行業務操作
- 執行txTestSayhiFeignClient.test2(String name)進行業務操作,拋出錯誤
- 自動執行txTestSayhiFeignClient.cancelTest2(String name)進行回滾操作
- 本地事務的回滾操作
4.回滾之後的Hook接口
當分佈式事務回滾之後,Beast-Tx提供了一個可供擴展的hook接口。
只要你的項目中實現了CancelInvokeHook這個接口並註冊到spring容器中。在項目啟動的時候就會被自動掃描到。
當你的分佈式事務回滾之後,會自動執行這個hook實現。你可以用來持久化錯誤信息,打印回滾鏈路,或者進行一些其他的業務操作。
5.監控的擴展
Beast-Tx留了一系列的監控擴展點。
5.1 監控的server端(半成品)
其中監控的server端為beast-tx-monitor,如啟動的話,這個項目目前只接受每一條的事務上下文並打印,並沒有對事務上下文作進一步的監控業務,如有興趣可以自行實現
5.2 client端
如果您在dubbo/Spring Cloud消費者端的application.yml配了如下配置
<code>tx:
monitor:
ip: 127.0.0.1
port: 6789/<code>
springboot啟動時會自動裝配,在每一個分佈式事務結束後,會把這個事務中的詳細內容發送到server端。
其中項目對socket提供了2個實現:
beast-tx-socket-netty
beast-tx-socket-tio
都是用SPI實現的,默認用netty,想換實現,只需換一個依賴包即可
閱讀更多 儒雅程序員 的文章