beast-tx一個輕量級不侵入業務代碼的TCC分佈式事務框架

概述

Beast-tx是一個輕量級不侵入業務代碼的TCC分佈式事務框架。支持dubbo和spring cloud。


beast-tx一個輕量級不侵入業務代碼的TCC分佈式事務框架


特性

  • 支持主流的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出錯。那整個執行順序如下:

  1. 先執行本地事務jdbcTemplate.execute("insert into user (name, age) values ('beast-tx', '99131')")
  2. 自動執行demoService.tryTest1(String name)進行業務前置判斷檢查
  3. 執行demoService.test1(String name)進行業務操作
  4. 執行demoService.test3(Long id)進行業務操作,拋出錯誤
  5. 自動執行demoService.cancelTest3(Long id)進行回滾操作
  6. 本地事務的回滾操作

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出錯。那整個執行順序如下:

  1. 先執行本地事務jdbcTemplate.execute("insert into user (name, age) values ('beast-tx', '99131')")
  2. 自動執行txTestSayhiFeignClient.tryTest1(String name)進行業務前置判斷檢查
  3. 執行txTestSayhiFeignClient.test1(String name)進行業務操作
  4. 執行txTestSayhiFeignClient.test2(String name)進行業務操作,拋出錯誤
  5. 自動執行txTestSayhiFeignClient.cancelTest2(String name)進行回滾操作
  6. 本地事務的回滾操作

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,想換實現,只需換一個依賴包即可


分享到:


相關文章: