Skip to content

基于Spring Cloud Netflix的Try-Confirm-Cancel柔性事务示例. 结合Spring Cloud Sleuth进行会话追踪和Spring Boot Admin的健康监控, 并辅以Hystrix Dashboard提供近实时的熔断监控.

Notifications You must be signed in to change notification settings

aqqvxdx/spring-cloud-rest-tcc

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

52 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Solar

Spring Cloud为开发者提供了快速构建分布式系统中的一些常见工具, 如分布式配置中心, 服务发现与注册中心, 智能路由, 服务熔断及降级, 消息总线, 分布式追踪的解决方案等.

本次实战以模拟下单流程为背景, 结合Spring Cloud Netflix与分布式事务中的Try-Confirm-Cancel即TCC模式作为实战演示.

开发环境

  • Docker 1.13.1
  • Docker Compose 1.11.1
  • Docker MySQL 5.7.17
  • Docker RabbitMQ 3.6.6
  • Java8 with JCE
  • Spring Cloud Camden.SR6

Try Confirm Cancel补偿模式

本实例遵循的是Atomikos公司对微服务的分布式事务所提出的RESTful TCC解决方案

RESTful TCC模式分3个阶段执行

  1. Trying阶段主要针对业务系统检测及作出预留资源请求, 若预留资源成功, 则返回确认资源的链接与过期时间
  2. Confirm阶段主要是对业务系统的预留资源作出确认, 要求TCC服务的提供方要对确认预留资源的接口实现幂等性, 若Confirm成功则返回204, 资源超时则证明已经被回收且返回404
  3. Cancel阶段主要是在业务执行错误或者预留资源超时后执行的资源释放操作, Cancel接口是一个可选操作, 因为要求TCC服务的提供方实现自动回收的功能, 所以即便是不认为进行Cancel, 系统也会自动回收资源

系统结构

基础组件

Zuul Gateway

Zuul在本实例中仅作为路由所使用, 配置降低Ribbon的读取与连接超时上限

Eureka H.A.

多个对等Eureka节点组成高可用集群, 并将注册列表的自我保护的阈值适当降低

Config Server

  • 如果远程配置中有密文{cipher}*, 那么该密文的解密将会延迟至客户端启动的时候. 因此客户端需要配置AES的对称密钥encrypt.key, 并且客户端所使用的JRE需要安装Java 8 JCE, 否则将会抛出Illegal key size相关的异常. (本例中Docker Compose构建的容器已经安装了JCE, 如果远程配置文件没有使用{cipher}*也不必进行JCE的安装)

  • 为了达到开箱即用, 选用公开仓库Github或者GitOsc

  • 本项目中有两个自定义注解 @com.github.prontera.Delay 控制方法的延时返回时间

    @com.github.prontera.RandomlyThrowsException 随机抛出异常, 人为地制造异常

    默认的远程配置如下

    solar:
      delay:
        time-in-millseconds: 0
      exception:
        enabled: false
        factor: 7

    这些自定义配置正是控制方法返回的时延, 随机异常的因子等

    我在服务order, product, accounttcc中的所有Controller上都添加了以上两个注解, 当远程配置的更新时候, 可以手工刷新/refresh或通过webhook等方法自动刷新本地配置. 以达到模拟微服务繁忙或熔断等情况.

RabbitMQ

原本作为可靠性事件投递的Broker, 如今被TCC模式所替代. 可为日后的Spring Cloud Steam或Spring Cloud Bus的集成作为基础组件而保留

监控服务

Spring Boot Admin

此应用提供了管理Spring Boot服务的简单UI, 下图是在容器中运行时的服务健康检测页

Hystrix Dashboard

提供近实时依赖的统计和监控面板, 以监测服务的超时, 熔断, 拒绝, 降级等行为

Zipkin Server

Zipkin是一款开源的分布式实时数据追踪系统, 其主要功能是聚集来自各个异构系统的实时监控数据, 用来追踪微服务架构下的系统时延问题. 下图是对order服务的请求进行追踪的情况

业务服务

首次启动时通过Flyway自动初始化数据库

对spring cloud config server采用fail fast策略, 一旦远程配置服务无法连接则无法启动业务服务

account

用于获取用户信息, 用户注册, 修改用户余额, 预留余额资源, 确认预留余额, 撤销预留余额

product

用于获取产品信息, 变更商品库存, 预留库存资源, 确认预留库存, 撤销预留库存

tcc coordinator

TCC资源协调器, 其职责如下

  • 对所有参与者发起Confirm请求
  • 无论是协调器发生的错误还是调用参与者所产生的错误, 协调器都必须有自动恢复重试功能, 尤其是在确认的阶段, 以防止网络抖动的情况

order

order服务是本项目的入口, 尽管所提供的功能很简单

  • 下单. 即生成预订单, 为了更好地测试TCC功能, 在下单时就通过Feign向服务accountproduct发起预留资源请求, 并且记录入库
  • 确认订单. 确认订单时根据订单ID从库中获取订单, 并获取预留资源确认的URI, 交由服务tcc统一进行确认, 如果发生冲突即记录入库, 等待人工处理

Swagger UI

下图为product服务的Swagger接口文档, 根据下文的服务字典可知, 本接口文档可通过http://localhost:8040/swagger-ui.html进行访问. order, accounttcc的文档访问方式亦是如出一撤

运行

Docker Compose运行

在项目根路径下执行脚本build.sh, 该脚本会执行Maven的打包操作, 并会迭代目录下的*-compose.yml进行容器构建

构建完成后需要按照指定的顺序启动

  1. 启动MySQL, RabbitMQ等基础组件

    ➜  solar git:(feature/cleanup) ✗ docker-compose -f infrastructure-compose.yml up -d
  2. 启动Eureka Server与Config Server

    ➜  solar git:(feature/cleanup) ✗ docker-compose -f basic-ms-compose.yml up -d
  3. 启动监控服务

    ➜  solar git:(feature/cleanup) ✗ docker-compose -f monitor-ms-compose.yml up -d
  4. 启动业务服务

    ➜  solar git:(feature/cleanup) ✗ docker-compose -f business-ms-compose.yml up -d

IDE运行

因为程序本身按照Docker启动, 所以对于hostname需要在hosts文件中设置正确才能正常运行

## solar
127.0.0.1 eureka1
127.0.0.1 eureka2
127.0.0.1 rabbitmq
127.0.0.1 zipkin_server
127.0.0.1 solar_mysql
127.0.0.1 gitlab

根据依赖关系, 程序最好按照以下的顺序执行

docker mysql > docker rabbitmq > eureka server > config server > zipkin server > 其他微服务

示例

根据附表中的服务字典, 我们通过Zuul或Swagge对order服务进行预订单生成操作

POST http://localhost:7291/order/api/v1/orders
Content-Type: application/json;charset=UTF-8

{
  "product_id": 7,
  "user_id": 1
}

成功后我们将得到预订单的结果

{
  "data": {
    "id": 15,
    "create_time": "2017-03-28T18:18:02.206+08:00",
    "update_time": "1970-01-01T00:00:00+08:00",
    "delete_time": "1970-01-01T00:00:00+08:00",
    "user_id": 1,
    "product_id": 7,
    "price": 14,
    "status": "PROCESSING"
  },
  "code": 20000
}

此时我们再确认订单

(如果想测试预留资源的补偿情况, 那么就等15s后过期再发请求, 注意容器与宿主机的时间)

POST http://localhost:7291/order/api/v1/orders/confirmation
Content-Type: application/json;charset=UTF-8

{
  "order_id": 15
}

如果成功确认则返回如下结果

{
  "data": {
    "id": 15,
    "create_time": "2017-03-28T18:18:02.206+08:00",
    "update_time": "2017-03-28T18:21:32.78+08:00",
    "delete_time": "1970-01-01T00:00:00+08:00",
    "user_id": 1,
    "product_id": 7,
    "price": 14,
    "status": "DONE"
  },
  "code": 20000
}

至此就完成了一次TCC事务, 当然你也可以测试超时和冲突的情况, 这里就不再赘述

拓展

使用Gitlab作为远程配置仓库

本例中默认使用Github或GitOsc中的公开仓库, 出于自定义的需要, 我们可以在本地构建Git仓库, 这里选用Gitlab为例.

将以下配置添加至docker compose中的文件中并启动Docker Gitlab容器

gitlab:
    image: daocloud.io/daocloud/gitlab:8.16.7-ce.0
    ports:
        - "10222:22"
        - "80:80"
        - "10443:443"
    volumes:
        - "./docker-gitlab/config/:/etc/gitlab/"
        - "./docker-gitlab/logs/:/var/log/gitlab/"
        - "./docker-gitlab/data/:/var/opt/gitlab/"
    environment:
        - TZ=Asia/Shanghai

将项目的config-repo添加至Gitlab中, 并修改config-ms中git仓库的相关验证等参数即可

服务字典

鉴于Spring Boot Actuator的端点所带来的两面性, 除了可以增加spring-boot-starter-security来获得强度较弱的HTTP Basic认证外, 我们还可以修改management.portmanagement.context-path来提高攻击成本. 是的, 我对每一个服务都修改了以上两个属性, 并且兼容了Eureka Server, Hystrix Dashboard, Spring Boot Admin, 使这些监控服务仍能正确工作. 因为对以上两个参数修改, 我们的监控路径有所变化, 如下表

module name docker compose service name application name server port management port management context path scalable
account-ms account account 10014 10248 /78d504ff-82e8-4a87-82e8-724d72d1171b
api-gateway-ms gateway gateway 7291 10211 /fb83deee-dd46-472b-99a9-f0ebffe20d0e
config-ms config_server config-server 10888 10481 /f7597180-e480-400e-81a0-847c22e2e0b8
eureka-registry-ms-1 eureka1 registry 8763 9274 /55395018-70b7-47c3-8fef-5bf24c9da9af ×
eureka-registry-ms-2 eureka2 registry 8762 10177 /e5da837b-a575-4447-b037-100850226a11 ×
hystrix-dashboard-ms hystrix_dashboard hystrix 8193 7104 /9511d89d-6488-4293-8df8-c4feb8681e83
order-ms order order 8295 10848 /78d504ff-82e8-4a87-82e8-724d72d1171b
product-ms product product 8040 10912 /78d504ff-82e8-4a87-82e8-724d72d1171b
spring-boot-admin-ms spring_boot_admin spring-boot-admin 7020 9218 /e58a0ff5-9f60-4545-9aa2-2b91c8a6d53b
tcc-coordinator-ms tcc_coordinator tcc 11020 12841 /78d504ff-82e8-4a87-82e8-724d72d1171b
zipkin-ms zipkin_server zipkin-server 9411 - - ×

结语

感谢你的耐心阅读, 如有对本项目中的Spring Cloud的使用或者对本人的编码风格有更好的想法或者建议, 欢迎通过邮件与我取得联系, 万分感谢

About

基于Spring Cloud Netflix的Try-Confirm-Cancel柔性事务示例. 结合Spring Cloud Sleuth进行会话追踪和Spring Boot Admin的健康监控, 并辅以Hystrix Dashboard提供近实时的熔断监控.

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 66.0%
  • Shell 19.9%
  • Batchfile 14.1%