前言本例基于Atomikos提出的微服务分布式事务的解决方案, 该方案建立在更加轻量级的HTTP协议之上, 原文如下 TCC for transaction management across microservices 根据Try Confirm Cancel补偿模式, 有关于Spring Cloud的实战如下 https://github.com/prontera/spring-cloud-rest-tcc 示例场景一个简单的TCC应用如下: 图中蓝色方框Booking Process代表订票系统, 该系统分别对swiss和easyjet发起预留机票资源的请求
角色这套API由3个角色组成: 参与者角色, 协调者角色和应用程序.
TCC服务提供方: 参与者API参与者职责参与者负责管理特定的业务资源. 默认情况下业务预留资源在一定时间后会超时, 除非该预留资源被协调器所确认. 自动超时和撤回每一个参与者的实现必须有自动Cancel超时资源的功能. 除非参与者接收到确认消息, 否则没有资源是不会过期的. 资源操作的入口每个参与者的实现必须返回一个用于调用Confirm的链接. 这些链接可以包含Confirm的URI, 自动过期时间等元数据. 下面是一个简单例子
实际上例子中的JSON只是建议格式, 真实使用的时候完全取决于双方的通信格式. PUT to Confirm在上述参与者返回的用于确认的链接中, 必须支持PUT方法以用于确认. 由于网络抖动等情况, 该操作必须具备幂等性.
注意请求头中MIME类型, 暗示了客户端的语义期望(可根据实际情况选择是否实现该MediaType). Confirm操作通常由协调者调用. 尽管参与者提供的API有指定的MIME类型, 但是这个类型仅仅用于指明语义, 实际上并不需要request body与response body. 如果一切正常, 那么参与者的响应如下
如果Confirm请求送达参与者后发现预留资源早就被Cancel或者已经超时被回滚, 那么参与者的API必须返回404错误
DELETE to Cancel: 可选实现每个参与者URI**或许**会有实现DELETE方法去显式地接受撤销请求. 由于网络抖动等情况, 该操作必须具备幂等性.
如果补偿成功则返回
因为参与者有实现自动撤销超时资源的职责, 那么如果在显式地调用Cancel的时候有其他错误发生, 那么这些错误都可以被忽略而且不影响整体的分布式事务 在内部事务已经超时或者已经被参与者自身补偿之后, 那么他可以直接返回404
因为DELETE请求是一个可选操作, 有些参与者可能没有实现这个功能, 在这个情况下可以返回405
GET方法故障诊断: 可选实现参与方服务可以实现GET方法来用于故障的诊断. 但是这个超出了REST TCC的简约协议的意图, 所以这个功能就由实际情况来决定是否实现 协调器API: 面向请求方的开发者协调器服务是由我们实现, 并交由请求方的开发人员使用. 因为这里从使用RESTful接口的设计角度来说明, 而不讨论协调器的内部实现. 协调器职责
PUT to Confirm请求方对协调器发出PUT请求来确认当前的分布式事务. 这些事务就是参与者之前返回给请求方的确认链接
然后协调器会对参与者逐个发起Confirm请求, 如果一切顺利那么将会返回如下结果
如果发起Confirm请求的时间太晚, 那么意味着所有被动方都已经进行了超时补偿
最最最糟糕的情况就是有些参与者确认了, 但是有些就没有. 这种情况就应该要返回409, 这种情况在Atomikos中定义为启发式异常
当然, 这种情况应该尽量地避免发生, 要求Confirm与Cancel实现幂等性, 出现差错时协调器可多次对参与者重试以尽量降低启发性异常发生的几率. 万一409真的发生了, 则应该由请求方主动进行检查或者由协调器返回给请求方详细的执行信息, 例如对每个参与者发起故障诊断的GET请求, 记录故障信息并进行人工干预. PUT to Cancel一个撤销请求跟确认请求类似, 都是使用PUT请求, 唯一的区别是URI的不同
唯一可预见的响应就是
因为当预留资源没有被确认时最后都会被释放, 所以参与者返回其他错误也不会影响最终一致性 |
|