本片文章是一篇servicecomb-pack的使用教程說明,理論知識會另起一篇文章再詳細說明(架構理論傳送門1,架構理論傳送門2)
servicecomb是華爲開源的一個微服務框架,後進入Apache軟件基金會孵化,現已畢業,是apache頂級開源項目,而servicecomb-pack是servicecomb孵化的三個子項目之一,是分佈式事務最終一致性解決方案,0.3.0版本之前叫saga,現改名爲servicecomb-pack,支持saga和tcc兩種分佈式事務協議,相關理論知識請移步(傳送門),本文主要介紹saga模式,下一篇介紹tcc模式
1.先配置和運行alpha-server
注意:alpha-server目前並沒有提供starter,因此需要從GitHub上獲取源碼本地自行編譯運行
源碼獲取
Github地址:https://github.com/apache/servicecomb-pack
git命令:$ git clone https://github.com/apache/servicecomb-pack.git
修改配置文件
找到alpha-server/src/main/resource/application.yaml,修改datasource信息爲本地信息即可
本地構建alpha-server
$ cd servicecomb-pack
只構建可執行文件(推薦)
$ mvn clean install -DskipTests -Pspring-boot-2
同時構建可執行文件和docker鏡像
$ mvn clean install -DskipTests -Pdocker,spring-boot-2
同時構建可執行文件以及pack發行包
$ mvn clean install -DskipTests -Prelease,spring-boot-2
在執行上面任一指令後,可在alpha/alpha-server/target/saga/alpha-server-${version}-exec.jar中找到alpha-server的可執行jar包
啓動alpha-server
通過docker運行:
docker run -d -p 8080:8080 -p 8090:8090 -e "JAVA_OPTS=-Dspring.profiles.active=prd -Dspring.datasource.url=jdbc:postgresql://${host_address}:5432/saga?useSSL=false" alpha-server:${saga_version}
通過可執行文件運行:
java -Dspring.profiles.active=prd -D"spring.datasource.url=jdbc:postgresql://${host_address}:5432/saga?useSSL=false" -jar alpha-server-${saga_version}-exec.jar
注意:請在執行命令前將${saga_version}和${host_address}更改爲實際值
至此,alpha-server全局事務管理器已經啓動成功
替換postgresql爲mysql
alpha-server默認使用postgresql,因此如想替換成mysql需以下步驟:
- 安裝並運行mysql
-
修改pom文件,添加依賴:alpha-server/pom.xml,添加mysql依賴(因爲配置文件中需要配置driver信息)
dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> <version>8.0.15</version> </dependency>
-
找到alpha-server/src/main/resource/application.yaml,修改datasource信息爲本地信息即可;注:url需添加serverTimezone,並增加driver-class-name屬性
spring: profiles: mysql datasource: username: ${username} password: ${password} url: jdbc:mysql://${host_address}:${port}/${database_name}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false platform: mysql continue-on-error: false driver-class-name: com.mysql.cj.jdbc.Driver jpa: properties: eclipselink: ddl-generation: none
注意:${username},${password},${host_address},${port},${database_name}需替換爲實際值
- 本地構建alpha-server(和上面步驟一致)
- 啓動alpha-server(和上面步驟一致)
2.Omega配置
添加依賴
<dependency>
<groupId>org.apache.servicecomb.pack</groupId>
<artifactId>omega-spring-starter</artifactId>
<version>${servicecomb-pack.version}</version>
</dependency>
<dependency>
<groupId>org.apache.servicecomb.pack</groupId>
<artifactId>omega-spring-cloud-consul-starter</artifactId>
<version>${servicecomb-pack.version}</version>
</dependency>
<dependency>
<groupId>org.apache.servicecomb.pack</groupId>
<artifactId>omega-transport-resttemplate</artifactId>
<version>${servicecomb-pack.version}</version>
</dependency>
注意:請將${servicecomb-pack.version}更改爲實際的版本號(目前最新release爲0.4.0)
修改配置文件
添加這一配置即可,其他應用配置自行添加,address可根據alpha-server中的配置實際添加
# 配置alpha-service 集羣/單機 服務訪問地址
alpha:
cluster:
address: localhost:8080
saga模式demo配置
添加saga的註解以及相關的補償方法配置
- 在應用入口添加@
EnableOmega
註解來初始化Omega的配置並與alpha-server建立連接(@EnableOmega註解在當前版本已經標註爲過時註解,但是不妨礙功能,後續應該會把註解轉換爲在配置文件中配置開關屬性,目前版本中還沒開始這種做)
@SpringBootApplication
@EnableOmega
public class CarApplication {
public static void main(String[] args) {
SpringApplication.run(CarApplication.class, args);
}
}
- 在全局事務的起點添加@SagaStart註解標註這是saga事務的start
@SagaStart(timeout = 5) //開啓saga分佈式事務,默認情況下,超時設置需要顯示聲明才生效
@GetMapping("/booking/{name}/{rooms}/{cars}")
public String booking(@PathVariable String name,@PathVariable Integer rooms,
@PathVariable Integer cars) throws Exception{}
注意:默認情況下,超時設置需要顯示聲明才能生效
- 在子事務處添加@
Compensable
註解並指明其對應的補償方法
@Override
@Transactional
@Compensable(timeout = 5, compensationMethod = "cancel")
public CarBooking order(CarBooking carBooking) {
return repository.save(carBooking);
}
補償方法
//補償邏輯 入參和try方法一致
@Transactional
public void cancel(CarBooking carBooking) {
//demo只進行取消/刪除 設置狀態; 實際開發中可針對實際業務進行邏輯編碼
//修改狀態
carBooking.setCancelled(Boolean.TRUE);
repository.save(carBooking);
//刪除記錄
// repository.delete(toSpecification(carBooking));
}
注意:實現的服務和補償方法必須滿足冪等的要求
注意:默認情況下,超時需要顯示聲明
注意:若全局事務起點與子事務重合,需同時聲明@SagaStart和@Compensable註解
注意:補償方法的入參必須與try方法入參一致,否則啓動時會報錯(alpha-server找不到補償方法)
至此,正常啓動服務即完成saga模式配置
tcc模式demo配置
- 在應用入口處添加@EnableOmega註解
@SpringBootApplication @EnableOmega public class OrderingApplication { public static void main(String[] args) { SpringApplication.run(OrderingApplication.class, args); } }
- 在全局事務的起點添加@TccStart註解標註這是tcc事務的start
@TccStart(timeout = 5) //當前版本的tcc還不支持timeout @PostMapping("/order/{userName}/{productName}/{productUnit}/{unitPrice}") public String order(@PathVariable String userName,@PathVariable String productName, @PathVariable Integer productUnit,@PathVariable Integer unitPrice) throws Exception{}
注意:當前版本tcc還不支持timeout
- 在子事務處添加@Participate註解並指明confirm和cancel方法
@Override @Transactional @Participate(confirmMethod = "confirm", cancelMethod = "cancel") public void reserve(ProductOrder productOrder) { Product product = new Product(); product.setName(productOrder.getProductName()); product = productRepository.findOne(toSpecification1(product)).get(); if (product.getInStock() >= productOrder.getUnits()) { product.setInStock(product.getInStock() - productOrder.getUnits()); productRepository.save(product); productOrderRepository.save(productOrder); } else { throw new IllegalArgumentException("The Product is out of stock!"); } }
確認方法
public void confirm(ProductOrder productOrder) { ...... }
補償方法
public void cancel(ProductOrder productOrder) { ...... }
注意:confirm和cancel方法的入參必須和try方法一致
至此,正常啓動服務即完成tcc模式配置
到此,saga和tcc已經基本搭建完成