项目演化过程中,微服务已经遍地开花。一个大项目下几十上百个微服务已经是常态。但衍生出另外一个问题就是跨微服务事务,跨库事务的分布式事务。市面了解过的有2CP、3CP、TCC等等分布式事务解决方案,各有优缺。对目前公司业务不太理想,DotNetCore.CAP的出现是从事.net开发者的福音。呵呵...
CAP概述
CAP 是一个事件总线EventBus,同时也是一个在微服务或者SOA系统中解决分布式事务问题的一个框架。它有助于创建可扩展,可靠并且易于更改的微服务系统。
CAP 采用模块化设计,具有高度的可扩展性。你有许多选项可以选择,包括消息队列,存储,序列化方式等,系统的许多元素内容可以替换为自定义实现。在 CAP 内部会将消息进行存储,以保证消息的可靠性,并配合重试等策略以达到各个服务之间的数据最终一致性。
什么是 EventBus?
事件总线是一种机制,它允许不同的组件彼此通信而不彼此了解。 组件可以将事件发送到Eventbus,而无需知道是谁来接听或有多少其他人来接听。 组件也可以侦听Eventbus上的事件,而无需知道谁发送了事件。 这样,组件可以相互通信而无需相互依赖。 同样,很容易替换一个组件。 只要新组件了解正在发送和接收的事件,其他组件就永远不会知道.
架构预览
CAP 支持以下几种运输方式
CAP 支持以下几种具有事务支持的数据库做为存储
CAP 监控
个人观点:
CAP与2CP、3CP、TCC不同之处,就是主业务本地事务提交成功后,没有回滚概念,所以性能相对高一些。子业务处理失败,会根据CAP配置策略进行重试,直至处理成功(达到策略次数后通过人工处理) 达到最终数据一致性。
注:因为有重试所以子业务必须处理重复消费MQ消息的业务处理来保证同消息不被成功处理N次。
案例说明
案例环境
window10、vs 2022、.net6.0、 mysql 5.6.39、RabbitMQ 3.6.6、Redis
VS 2022 新增两个项目:ASP.NET Core Web应用(模型-视图-控制器)、ASP.NET Core Web API
项目来代表主业务微服务、子业务微服务
NuGet 添加包引用安装
<PackageReference Include="DotNetCore.CAP" Version="6.1.0" />
<PackageReference Include="DotNetCore.CAP.Dashboard" Version="6.1.0" />
<PackageReference Include="DotNetCore.CAP.InMemoryStorage" Version="6.1.0" />
<PackageReference Include="DotNetCore.CAP.MySql" Version="6.1.0" />
<PackageReference Include="DotNetCore.CAP.RabbitMQ" Version="6.1.0" />
<PackageReference Include="DotNetCore.CAP.RedisStreams" Version="6.1.0" />
根据自身所需安装对应运输、存储、监控对应包
Cap相关注入
两个项目都注入cap,数据库可以配置同一个,也可以分开
启动项目会自动生成两个表
Published 表结构:
NAME | DESCRIPTION | TYPE |
Id | Message Id | int |
Version | Message Version | string |
Name | Topic Name | string |
Content | Json Content | string |
Added | Added Time | DateTime |
ExpiresAt | Expire time | DateTime |
Retries | Retry times | int |
StatusName | Status Name | string |
Received 表结构:
NAME | DESCRIPTION | TYPE |
Id | Message Id | int |
Version | Message Version | string |
Name | Topic Name | string |
Group | Group Name | string |
Content | Json Content | string |
Added | Added Time | DateTime |
ExpiresAt | Expire time | DateTime |
Retries | Retry times | int |
StatusName | Status Name | string |
生产者与消费者
主项目添加生产消息PublishController
同项目下两个子业务订阅了send、send1消息,携带请求头信息,不同项目子业务订阅了send2消息,指定callbackName进行回调
子项目添加消费消息ConsumerController
启动两个项目,主项目监控配置用的是Dashboard。所以我们可以访问/cap 进行可视化Published、Received 成功和失败内容
RabbitMq自动创建内容: 如果注入时没配置Exchanges,将自动生成一个Exchanges:cap.default.router
调用send
主业务广播一条消息
子业务接收消费消息:group1、group2各一条
调用send1
假设子业务处理异常,广播消息成功,消费失败,将按策略配置进行重试
过一段时间回头看看,重试次数一直在加,直到我们配置的20次后停止,进行邮件发送通知人工处理
调用send2
参考文档:https://cap.dotnetcore.xyz/user-guide/zh/getting-started/quick-start/