博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Cloud综合实战 - 基于TCC补偿模式的分布式事务
阅读量:5936 次
发布时间:2019-06-19

本文共 5960 字,大约阅读时间需要 19 分钟。

本文通过使用Spring Cloud和Docker构建了一个常见的Microservice体系.

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

而Spring Cloud Sleuth为Spring Cloud提供了分布式追踪方案, 可视化地分析服务调用链路和服务间的依赖关系

本次实战以模拟下单流程作为实战演示, 使用Try-Confirm-Cancel即TCC模式为分布式事务提供最终一致性.

Try Confirm Cancel补偿模式

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

RESTful TCC模式分3个阶段执行

Trying阶段主要针对业务系统检测及作出预留资源请求, 若预留资源成功, 则返回确认资源的链接与过期时间

Confirm阶段主要是对业务系统的预留资源作出确认, 要求TCC服务的提供方要对确认预留资源的接口实现幂等性, 若Confirm成功则返回204, 资源超时则证明已经被回收且返回404
Cancel阶段主要是在业务执行错误或者预留资源超时后执行的资源释放操作, Cancel接口是一个可选操作, 因为要求TCC服务的提供方实现自动回收的功能, 所以即便是不认为进行Cancel, 系统也会自动回收资源
系统结构
Spring Cloud综合实战 - 基于TCC补偿模式的分布式事务
基础组件
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的安装)

spring:  cloud:    config:      server:        git:          uri: 'https://git.oschina.net/witless/conf-repo.git'          clone-on-start: true        encrypt:          enabled: false  application:    name: 'config-server'

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

本项目中有两个自定义注解

@com.github.prontera.Delay 控制方法的延时返回时间

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

默认的远程配置如下

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

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

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

RabbitMQ

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

监控服务

Spring Boot Admin
此应用提供了管理Spring Boot服务的简单UI, 下图是在容器中运行时的服务健康检测页
Spring Cloud综合实战 - 基于TCC补偿模式的分布式事务
Hystrix Dashboard
提供近实时依赖的统计和监控面板, 以监测服务的超时, 熔断, 拒绝, 降级等行为
Spring Cloud综合实战 - 基于TCC补偿模式的分布式事务
Zipkin Server
Zipkin是一款开源的分布式实时数据追踪系统, 其主要功能是聚集来自各个异构系统的实时监控数据, 用来追踪微服务架构下的系统时延问题. 下图是对order服务的请求进行追踪的情况

Spring Cloud综合实战 - 基于TCC补偿模式的分布式事务

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

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

account

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

product

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

tcc coordinator

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

对所有参与者发起Confirm请求

无论是协调器发生的错误还是调用参与者所产生的错误, 协调器都必须有自动恢复重试功能, 尤其是在确认的阶段, 以防止网络抖动的情况
order
order服务是本项目的入口, 尽管所提供的功能很简单

下单. 即生成预订单, 为了更好地测试TCC功能, 在下单时就通过Feign向服务account与product发起预留资源请求, 并且记录入库

确认订单. 确认订单时根据订单ID从库中获取订单, 并获取预留资源确认的URI, 交由服务tcc统一进行确认, 如果发生冲突即记录入库, 等待人工处理
Spring Cloud综合实战 - 基于TCC补偿模式的分布式事务
与其他服务进行通讯, 我们选择使用Feign

/** * @author Zhao Junjian */@FeignClient(name = TccClient.SERVICE_ID, fallback = TccClientFallback.class)public interface TccClient {    /**     * eureka service name     */    String SERVICE_ID = "tcc";    /**     * api prefix     */    String API_PATH = "/api/v1/coordinator";    @RequestMapping(value = API_PATH + "/confirmation", method = RequestMethod.PUT, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}, consumes = {MediaType.APPLICATION_JSON_UTF8_VALUE})    void confirm(@RequestBody TccRequest request);    @RequestMapping(value = API_PATH + "/cancellation", method = RequestMethod.PUT, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}, consumes = {MediaType.APPLICATION_JSON_UTF8_VALUE})    void cancel(@RequestBody TccRequest request);}

Swagger UI

Swagger的目标是为REST APIs 定义一个标准的, 与语言无关的接口, 使人和计算机在看不到源码或者看不到文档或者不能通过网络流量检测的情况下能发现和理解各种服务的功能. 当服务通过Swagger定义, 消费者就能与远程的服务互动通过少量的实现逻辑. 类似于低级编程接口, Swagger去掉了调用服务时的很多猜测.
Spring Cloud综合实战 - 基于TCC补偿模式的分布式事务
运行
Docker Compose运行
在项目根路径下执行脚本build.sh, 该脚本会执行Maven的打包操作, 并会迭代目录下的*-compose.yml进行容器构建

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

启动MySQL, RabbitMQ等基础组件

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

启动Eureka Server与Config Server

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

启动监控服务

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

启动业务服务

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

IDE运行

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

## solar127.0.0.1 eureka1127.0.0.1 eureka2127.0.0.1 rabbitmq127.0.0.1 zipkin_server127.0.0.1 solar_mysql127.0.0.1 gitlab

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

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

示例

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

POST http://localhost:7291/order/api/v1/ordersContent-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/confirmationContent-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 Cloud综合实战 - 基于TCC补偿模式的分布式事务

针对上面的技术我特意整理了一下,有很多技术不是靠几句话能讲清楚,所以干脆找朋友录制了一些视频,很多问题其实答案很简单,但是背后的思考和逻辑不简单,要做到知其然还要知其所以然。如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java进阶群:855801563,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

1.具有1-5工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加群。

2.在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加群。

3.如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的可以加群。

转载于:https://blog.51cto.com/13981400/2321139

你可能感兴趣的文章
EF 通过DataAnnotations配置属性和类型
查看>>
C#多线程学习一
查看>>
删除数组中的空元素
查看>>
spring学习笔记
查看>>
Git使用技巧(3)-- 远程操作
查看>>
请问ECSHOP首页站内快讯在哪里添加和修改?
查看>>
人工智能----TensorFlow开篇简介
查看>>
第五次实验
查看>>
数论概论(Joseph H.Silverman) 习题 5.3,Elementary methods in number theory exercise 1.3.23
查看>>
python ORM理解、元类
查看>>
2018软工实践第一次作业
查看>>
Weekly 4
查看>>
线性表之单链表
查看>>
DP+矩阵快速幂 HDOJ 5318 The Goddess Of The Moon
查看>>
在朗沃这段时间的学习感想
查看>>
(转载)RabbitMQ消息队列应用
查看>>
【转】大型网站后台架构的演变
查看>>
几招防范Java漏洞
查看>>
『003』索引-脚本
查看>>
CH5102 Mobile Service
查看>>