最近項目中要用到分佈式事務功能,調研了DTM和Cap,最終確定用Cap來實現,Cap支持最終一致性,項目中採用MQ作爲消息中間件,數據庫用的mysql,集成步驟如下:
1、在需要發佈消息的服務中引入如下的包,我是放在了api層
<PackageReference Include="DotNetCore.CAP" Version="5.2.0" /> <PackageReference Include="DotNetCore.CAP.Dashboard" Version="5.2.0" /> <PackageReference Include="DotNetCore.CAP.MySql" Version="5.2.0" /> <PackageReference Include="DotNetCore.CAP.RabbitMQ" Version="5.2.0" />
2、編寫Cap擴展服務
public static class CapExtensions { public static void AddMyCap(this IServiceCollection services, IConfiguration configuration) { services.AddCap( a => { a.UseEntityFramework<QualificationDbContext>(); a.UseMySql(configuration.GetConnectionString("Default")); //僅用於測試,正式使用後要換成可配置項 a.UseRabbitMQ(rb => { rb.HostName = "118.111.111.111"; rb.UserName = "root"; rb.Password = "123456"; rb.Port = 5672; rb.VirtualHost = "/"; }); // 添加cap後臺監控頁面(人工處理);頁面地址爲“/cap”;如:http://www.site.com/cap a.UseDashboard(); // 配置定時器重試策略 a.FailedRetryInterval = 10; //重試間隔時間(秒),使用默認的就可以,可不用配置 a.FailedRetryCount = 5; //重試次數 } ); services.AddDbContext<QualificationDbContext>(); } }
3、在配置文件中增加服務
context.Services.AddMyCap(configuration);
4、在控制器中註冊ICapPublisher類就可以發佈消息了
namespace Qualification.Controllers { [Route("api/Test")] public class TestController : AbpController { private readonly ICapPublisher capPublisher; public TestController(ICapPublisher _capPublisher) { this.capPublisher = _capPublisher; } /// <summary> /// 測試cap功能:創建證照時發佈消息,在服務平臺進行訂閱 /// </summary> /// <returns></returns> [HttpPost("CreateQualification")] public async Task<IActionResult> CreateQualification() { try { this.capPublisher.Publish<CreateQualificationCapDto>("Qualification.Create.Success", new CreateQualificationCapDto { Name = "Qualification", Count = 10 }); return Ok("創建產品證照成功"); } catch (Exception ex) { throw; } } } public class CreateQualificationCapDto { public string Name { get; set; } public int Count { get; set; } } }
3、在訂閱的程序b中同樣引用cap的依賴包
4、同樣寫Cap服務的擴展程序,和服務a是一樣的,這裏就不再重複了
5、在訂閱服務類中繼承ICapSubscribe,因爲我是用的ABP框架,所以繼承了ITransientDependency接口,爲了是注入服務實體,如果你不是用這個框架,請在手動注入服務:services.AddSingleton<Controllers.CapSubscribeService>();否則,訂閱不到數據。
public interface ICapSubscribeService { public void UpdateOrder(CreateQualificationCapDto createQualification); } public class CapSubscribeService : ICapSubscribeService, ICapSubscribe, ITransientDependency { [CapSubscribe("Qualification.Create.Success")] public void UpdateOrder(CreateQualificationCapDto createQualification) { var data = createQualification; } } public class CreateQualificationCapDto { public string Name { get; set; } public int Count { get; set; } }
6、同時啓動兩個系統數據庫中會自動生成兩個表
7、服務a中發佈一個消息後在服務b中會自動訂閱到
8、系統爲我們默認生成了交換機和隊列,並且可以查看到發了信息
9、後續還會加上發佈消息時與業務代碼處理放在一個事務中,發佈與訂閱錯誤時回調方法。