一、什么是Cap   

CAP 是一个基于 .NET Standard 的 C# 库,它是一种处理分布式事务的解决方案,同样具有 EventBus 的功能,它具有轻量级、易使用、高性能等特点。

在我们构建 SOA 或者 微服务系统的过程中,我们通常需要使用事件来对各个服务进行集成,在这过程中简单的使用消息队列并不能保证数据的最终一致性, CAP 采用的是和当前数据库集成的本地消息表的方案来解决在分布式系统互相调用的各个环节可能出现的异常,它能够保证任何情况下事件消息都是不会丢失的。

你同样可以把 CAP 当做 EventBus 来使用,CAP提供了一种更加简单的方式来实现事件消息的发布和订阅,在订阅以及发布的过程中,你不需要继承或实现任何接口。

以下是CAP集在ASP.NET Core 微服务架构中的一个示意图:

二、安装

你可以运行以下下命令在你的项目中安装 CAP。

PM> Install-Package DotNetCore.CAP
CAP 支持 Kafka、RabbitMQ、AzureServiceBus 等消息队列,你可以按需选择下面的包进行安装:

PM> Install-Package DotNetCore.CAP.Kafka
PM> Install-Package DotNetCore.CAP.RabbitMQ
PM> Install-Package DotNetCore.CAP.AzureServiceBus

我们这里采用RabbitMQ,安装教程请转到另一篇文章:Winows下安装RabbitMQ

CAP 提供了 Sql Server, MySql, PostgreSQL,MongoDB 的扩展作为数据库存储:

// 按需选择安装你正在使用的数据库
PM> Install-Package DotNetCore.CAP.SqlServer
PM> Install-Package DotNetCore.CAP.MySql
PM> Install-Package DotNetCore.CAP.PostgreSql
PM> Install-Package DotNetCore.CAP.MongoDB

我们这里采用SqlServer

三、配置

首先配置CAP到 Startup.cs 文件中,如下:

public void ConfigureServices(IServiceCollection services)
{
...... services.AddDbContext<AppDbContext>(); services.AddCap(x =>
{
//如果你使用的 EF 进行数据操作,你需要添加如下配置:
x.UseEntityFramework<AppDbContext>(); //可选项,你不需要再次配置 x.UseSqlServer 了 //如果你使用的ADO.NET,根据数据库选择进行配置:
x.UseSqlServer("数据库连接字符串");
x.UseMySql("数据库连接字符串");
x.UsePostgreSql("数据库连接字符串"); //如果你使用的 MongoDB,你可以添加如下配置:
x.UseMongoDB("ConnectionStrings"); //注意,仅支持MongoDB 4.0+集群 //CAP支持 RabbitMQ、Kafka、AzureServiceBus 等作为MQ,根据使用选择配置:
x.UseRabbitMQ("ConnectionStrings");
x.UseKafka("ConnectionStrings");
x.UseAzureServiceBus("ConnectionStrings");
});
}

我们这里采用EF数据库配置和RabbitMQ如下:

services.AddCap(x =>
{
//如果你使用的 EF 进行数据操作,你需要添加如下配置:
x.UseEntityFramework<SysContext>(); x.UseRabbitMQ("localhost"); });

四、启动

运行程序,将在数据库生成Cap.Published和Cap.Received表如下图所示:

五、发布和订阅

在 Controller 中注入 ICapPublisher 然后使用 ICapPublisher 进行消息发送

      private readonly ICapPublisher _capBus;

        public ValuesController(ICapPublisher capPublisher)
{
_capBus = capPublisher; }
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{ _capBus.Publish("xxx.services.show.time", DateTime.Now);
return new string[] { "value1", "value2" };
}
[CapSubscribe("xxx.services.show.time")]
public void ShowTime(DateTime datetime)
{
}

运行程序,Cap.Published和Cap.Received将生成发布消息和订阅消息的记录

如果你的订阅方法没有位于 Controller 中,则你订阅的类需要继承 ICapSubscribe:

namespace xxx.Service
{
public interface ISubscriberService
{
public void CheckReceivedMessage(DateTime datetime);
} public class SubscriberService: ISubscriberService, ICapSubscribe
{
[CapSubscribe("xxx.services.show.time")]
public void CheckReceivedMessage(DateTime datetime)
{
}
}
}

然后在 Startup.cs 中的 ConfigureServices() 中注入你的 ISubscriberService 类

public void ConfigureServices(IServiceCollection services)
{
//注意: 注入的服务需要在 `services.AddCap()` 之前
services.AddTransient<ISubscriberService,SubscriberService>(); services.AddCap(x=>{});
}

六、订阅者组
订阅者组的概念类似于 Kafka 中的消费者组,它和消息队列中的广播模式相同,用来处理不同微服务实例之间同时消费相同的消息。

当CAP启动的时候,她将创建一个默认的消费者组,如果多个相同消费者组的消费者消费同一个Topic消息的时候,只会有一个消费者被执行。 相反,如果消费者都位于不同的消费者组,则所有的消费者都会被执行。

相同的实例中,你可以通过下面的方式来指定他们位于不同的消费者组。

[CapSubscribe("xxx.services.show.time", Group = "group1" )]
public void ShowTime1(DateTime datetime)
{
} [CapSubscribe("xxx.services.show.time", Group = "group2")]
public void ShowTime2(DateTime datetime)
{
}

ShowTime1 和 ShowTime2 处于不同的组,他们将会被同时调用。

PS,你可以通过下面的方式来指定默认的消费者组名称:

services.AddCap(x =>
{
x.DefaultGroup = "default-group-name";
});

七、Dashboard
CAP 2.1+ 以上版本中提供了仪表盘(Dashboard)功能,你可以很方便的查看发出和接收到的消息。除此之外,你还可以在仪表盘中实时查看发送或者接收到的消息。

在分布式环境中,仪表盘内置集成了 Consul 作为节点的注册发现,同时实现了网关代理功能,你同样可以方便的查看本节点或者其他节点的数据,它就像你访问本地资源一样。

services.AddCap(x =>
{
//... // 注册 Dashboard
x.UseDashboard(); // 注册节点到 Consul
x.UseDiscovery(d =>
{
d.DiscoveryServerHostName = "localhost";
d.DiscoveryServerPort = ;
d.CurrentNodeHostName = "localhost";
d.CurrentNodePort = ;
d.NodeId = ;
d.NodeName = "CAP No.1 Node";
});
});

仪表盘默认的访问地址是:http://localhost:xxx/cap,你可以在d.MatchPath配置项中修改cap路径后缀为其他的名字。

参考资料:https://github.com/dotnetcore/CAP/blob/master/README.zh-cn.md

使用Cap解决.Netcore分布式事务的更多相关文章

  1. CAP理论与分布式事务解决方案

    微服务系统所设计的系统是分布式系统.分布式系统有一个著名的CAP理论,即同时满足"一致性""可用性"和"分区容错"是一件不可能的事.CAP理 ...

  2. cap理论与分布式事务的解决方案

    现在很火的微服务架构所设计的系统是分布式系统.分布式系统有一个著名的CAP理论,即一个分布式系统要同时满足一致性(Consistency).可用性(Availablility)和分区容错(Partit ...

  3. .netcore 分布式事务CAP2.6之控制台使用

    上一编讲了cap2.6的快速入门,这次我们来讲讲在控制台中如何使用cap2.6.因为cap2.6的内存模式目前已经可以使用了,相关组件已经更新,所以这次我们以简单的内存模式为例. 1:创建项目 创建一 ...

  4. .NET Core 事件总线,分布式事务解决方案:CAP

    背景 相信前面几篇关于微服务的文章也介绍了那么多了,在构建微服务的过程中确实需要这么一个东西,即便不是在构建微服务,那么在构建分布式应用的过程中也会遇到分布式事务的问题,那么 CAP 就是在这样的背景 ...

  5. .NET Core 事件总线,分布式事务解决方案:CAP 基于Kafka

    背景 相信前面几篇关于微服务的文章也介绍了那么多了,在构建微服务的过程中确实需要这么一个东西,即便不是在构建微服务,那么在构建分布式应用的过程中也会遇到分布式事务的问题,那么 CAP 就是在这样的背景 ...

  6. 【转】.NET Core 事件总线,分布式事务解决方案:CAP

    [转].NET Core 事件总线,分布式事务解决方案:CAP 背景 相信前面几篇关于微服务的文章也介绍了那么多了,在构建微服务的过程中确实需要这么一个东西,即便不是在构建微服务,那么在构建分布式应用 ...

  7. LCN解决分布式事务原理解析+项目实战(原创精华版)

    写在前面: 原创不易,如果觉得不错推荐一下,谢谢! 由于工作需要,公司的微服务项目需解决分布式事务的问题,且由我进行分布式事务框架搭建和整合工作. 那么借此机会好好的将解决分布式事务的内容进行整理一下 ...

  8. 一文教你迅速解决分布式事务 XA 一致性问题

    欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 作者:腾讯云数据库团队 近日,腾讯云发布了分布式数据库解决方案(DCDB),其最明显的特性之一就是提供了高于开源分布式事务XA的性能.大型 ...

  9. asp.net core集成CAP(分布式事务总线)

    一.前言 感谢杨晓东大佬为社区贡献的CAP开源项目,传送门在此:.NET Core 事件总线,分布式事务解决方案:CAP 以及 如何在你的项目中集成 CAP[手把手视频教程],之前也在工作中遇到分布式 ...

随机推荐

  1. Type of the default value for 'songs' prop must be a function

    eslint常会出现这样的错误提示,控制台打印:Type of the default value for 'songs' prop must be a function 解决办法有两种如下: 1:写 ...

  2. 2018.8.9 python中的动态传参与命名空间

    主要内容: 1.函数参数 ----动态传参 2.名称空间与作用域 3.函数的嵌套 4.global,nonlocal关键字 一.函数参数 ------动态传参 形参的第三种:动态传参 动态传参分为两种 ...

  3. Flask:网页路由及请求方式的设定

    1.Flask路由的实现 Flask的路由是由route装饰器来实现的 @app.route("/index/") def index(): return "hello ...

  4. 就因为加了Lombok的@Accessors(chain = true),bean拷贝工具类不干活了

    前言 这次新建了一个工程,因为 Lombok 用得很习惯,但以前的话,一般只用了@Data,@AllArgsConstructor,@EqualsAndHashCode等常规注解:那这个Accesso ...

  5. 在windows主机中,利用XSHELL生成“密钥”进行虚拟机与物理机的传输

    首先你要有虚拟机,其次你要可以互相ping通(主机与虚拟机) 接着你要有xshell 软件  没有的话可以点击链接下载 Xshell  6  提取码:cj5t 打开Xshell软件  在工具栏中选择“ ...

  6. 《Effective Java》 读书笔记(八)避免使用Finalizer和Cleaner机制

    Finalizer和Cleaner并不等同于C++中的析构函数,是不确定多久会被调用的,甚至有时候可能不会被调用,因此除了作为一个安全网或者终止非关键的本地资源,不应该在Finalizer或Clean ...

  7. 洛谷P5522 【[yLOI2019] 棠梨煎雪】

    区间操作考虑用线段树维护. 建\(n*2\)棵线段树,前\(n\)棵线段树维护每个串的第i位是否是0. 后\(n\)棵线段树维护每个串的第i位是否是1. 如果是问号的话,直接跳过就好(通过1和0能看出 ...

  8. SpringBoot系列:Spring Boot定时任务Spring Schedule

    Spring Schedule是Spring提供的定时任务框架,相较于Quartz,Schedule更加简单易用,在中小型应用中,对于大部分需求,Schedule都可以胜任. 一.Spring Sch ...

  9. Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/util/PatternMatchUtils

    { "message": "Handler dispatch failed; nested exception is java.lang.NoClassDefFoundE ...

  10. K8S入门系列之集群二进制部署-->node篇(三)

    node节点组件 docker kubelet kube-proxy kubernetes-server-linux-amd64.tar.gz(相关的这里都能找到二进制文件!) falnnel 1. ...