分布式事务和事务总线 DotNetCoreCap 使用实例

1 创建 CAP.UserService 项目, 安装包 DotNetCore.CAP.SqlServer 和 DotNetCore.CAP.RabbitMQ

在项目 Startup.cs  ConfigureServices 方法中调用如下注册方法

        #region 使用 DotNetCore.CAP 
        /// <summary>
        /// 注册 DotNetCore.CAP 
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddNetCoreCAP(this IServiceCollection services)
        {
            services.AddCap(x =>
            {
                x.UseSqlServer(options =>
                {
                    options.ConnectionString = ConfigurationHelper.GetSection("DatabaseConnectionStrings:SqlServer");
                });
                x.UseRabbitMQ(options =>
                {
                    options.HostName = ConfigurationHelper.GetSection("RabbitSettings:Host");
                    options.Port = Convert.ToInt32(ConfigurationHelper.GetSection("RabbitSettings:Port"));
                    options.UserName = ConfigurationHelper.GetSection("RabbitSettings:UserName");
                    options.Password = ConfigurationHelper.GetSection("RabbitSettings:Password");
                });

                //失败后的重试次数,默认50次;在FailedRetryInterval默认60秒的情况下,即默认重试50*60秒(50分钟)之后放弃失败重试
                x.FailedRetryCount = 10;

                //失败后的重拾间隔,默认60秒
                x.FailedRetryInterval = 60;

                // 推送到 RabbitMq 失败后的回调
                x.FailedThresholdCallback = failed => { 
                    
                };
            });
        }
        #endregion

2 启动项目,成功启动后会在数据库创建  cap.Published 和 cap.Received 两张表

3 编写订阅消息的代码 

先写订阅代码是为了先绑定队列到交换器,不然如果先定义了交换器,但没有队列,会导致消息丢失

        /// <summary>
        /// 订阅消息
        /// </summary>
        /// <param name="sysUserEntity">发布时传递的参数</param>
        /// <param name="header">发布时传递header</param>
        /// <returns></returns>
        [NonAction]
        [CapSubscribe("RabbitMQ.SqlServer.UserService", Group = "UserService.Distributed")]
        // RabbitMQ.SqlServer.UserService 与发布消息设置的 publishName 一致 ; Group 是队列名,会生成 UserService.Distributed.V1 队列)]
        public IActionResult Consumer(SysUserEntity sysUserEntity, [FromCap] CapHeader header)
        {
            return Ok();
        }

项目启动成功后会自动创建cap框架默认的交换器  cap.default.router

 然后会创建 队列 UserService.Distributed.v1 (队列名规则 Group.v1)

 

 再声明一个订阅者2

        [NonAction]
        [CapSubscribe("RabbitMQ.SqlServer.UserService", Group = "UserService.Aistributed")]
        // RabbitMQ.SqlServer.UserService 与发布消息设置的 publishName 一致 ; Group 是队列名,会生成 UserService.Aistributed.V1 队列)]
        public IActionResult Consumer2(SysUserEntity sysUserEntity, [FromCap] CapHeader header)
        {
            return Ok();
        }

同理会创建队列 UserService.Aistributed.V1

4 编写发布消息的代码

        public IActionResult Distributed()
        {
            IDictionary<string, string> dicHeaders = new Dictionary<string, string>();
            dicHeaders.Add("Day", "20220428");

            using (var trans = _userDbContext.Database.BeginTransaction(_capPublisher, autoCommit: false))
            {
                var user = new SysUserEntity { Id = Guid.NewGuid().ToString(), UserCode = "UserCode2", UserName = "UserName2" };
                _userDbContext.SysUsers.Add(user);
                _capPublisher.Publish(PublishName, user, dicHeaders);
                _userDbContext.SaveChanges();
                trans.Commit();
            }

            return Ok();
        }

发布成功后,Published 表有一条记录

 即使rabbitmq没有启动程序也能正常返回响应因为cap 框架有后台任务来重推信息到mq中。

5 测试

发布新消息前,在 订阅者代码处打上断点,接收到了发布的消息

 

 

 查询 Received表看到接收到两天记录

 

 

参考资源

https://www.bilibili.com/video/BV1b44y1H7yM?p=104&spm_id_from=pageDriver

posted @ 2022-05-03 17:57  温故纳新  阅读(419)  评论(0编辑  收藏  举报