servicecomb-pack分佈式事務解決方案之學習之路(一):saga和tcc-spring-demo

本片文章是一篇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(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已經基本搭建完成

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章