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

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: .NET Core 事件总线,分布式事务解决方案:CAP

数据库代码


CREATE DATABASE OrderTest;
GO
USE OrderTest;
GO
CREATE TABLE Product(
  Id INT PRIMARY KEY IDENTITY,
  ProductName VARCHAR(30) NOT NULL,
  Price INT NOT NULL,
  Stock INT NOT NULL
);
CREATE TABLE [Order]
(
  Id INT PRIMARY KEY IDENTITY,
  ProductId INT NOT NULL,
  UserName VARCHAR(30) NOT NULL,
  Quantity INT NOT NULL
);
GO
INSERT INTO dbo.Product
(
    ProductName,
    Price,
    Stock
)
VALUES ('衣服',30,30 ),('鞋子',20,20 ),('帽子',10,10 ),('外套',25,30 )


官网:https://cap.dotnetcore.xyz/user-guide/zh/getting-started/quick-start/


背景


在构建分布式应用的过程中也会遇到分布式事务的问题,那么 CAP 就是在这样的背景下诞生的。


https://github.com/dotnetcore


CAP 介绍


Github:https://github.com/dotnetcore/CAP


开源协议:MIT


CAP 是一个在分布式系统中(SOA,MicroService)实现事件总线及最终一致性(分布式事务)的一个开源的 C# 库,她具有轻量级,高性能,易使用等特点。


你可以轻松的在基于 .NET Core 技术的分布式系统中引入CAP,包括但限于 ASP.NET Core 和 ASP.NET Core on .NET Framework。


CAP 以 NuGet 包的形式提供,对项目无任何入侵,你仍然可以以你喜爱的方式来构建分布式系统。


CAP 具有 Event Bus 的所有功能,并且CAP提供了更加简化的方式来处理EventBus中的发布/订阅。


CAP 具有消息持久化的功能,也就是当你的服务进行重启或者宕机时,她可以保证消息的可靠性。


CAP 实现了分布式事务中的最终一致性,你不用再去处理这些琐碎的细节。


CAP 提供了基于 Microsoft DI 的 API 服务,她可以和你的 ASP.NET Core 系统进行无缝结合,并且能够和你的业务代码集成支持强一致性的事务处理。


CAP 是开源免费的。CAP基于MIT协议开源,你可以免费的在你的私人或者商业项目中使用,不会有人向你收取任何费用。


Getting Started


目前, CAP 同时支持使用 RabbitMQ,Kafka,Azure Service Bus 等进行底层之间的消息发送,你不需要具备这些消息队列的使用经验,仍然可以轻松的集成到项目中。


CAP 目前支持使用 Sql Server,MySql,PostgreSql,MongoDB 数据库的项目。


CAP 同时支持使用 EntityFrameworkCore 和 ADO.NET 的项目,你可以根据需要选择不同的配置方式。


下面是CAP在系统中的一个不完全示意图:

1673442616030.jpg

图中实线部分代表用户代码,虚线部分代表CAP内部实现。


下面,我们看一下 CAP 怎么集成到项目中:


Step 1:

你可以运行下面的命令来安装CAP NuGet 包:

PM> Install-Package DotNetCore.CAP


根据底层消息队列,你可以选择引入不同的包:

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


CAP 目前支持使用 SQL Server, PostgreSql, MySql, 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     //需要 MongoDB 4.0+ 集群


Step 2:

在 Startup.cs 文件中,添加如下配置:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    var sqlConnection = Configuration.GetConnectionString("OrderTestConnection");
    services.AddDbContext<OrderDbContext>(p=>p.UseSqlServer(sqlConnection));
    RabbitMQOptions rabbitOptions = new RabbitMQOptions();
    Configuration.GetSection("RabbitMQ").Bind(rabbitOptions);
    services.AddCap(p =>
                    {
                        p.UseEntityFramework<OrderDbContext>();
                        p.UseRabbitMQ(mq =>
                                      {
                                          mq.HostName = rabbitOptions.HostName;
                                          mq.VirtualHost = rabbitOptions.VirtualHost;
                                          mq.UserName = rabbitOptions.UserName;
                                          mq.Password = rabbitOptions.Password;
                                          mq.Port = rabbitOptions.Port;
                                      });
                        p.UseSqlServer(sqlConnection);
                    });
}


Step 3:

appsetting.json 文件配置:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
    "AllowedHosts": "*",
    "ConnectionStrings": {
        "OrderTestConnection": "server=.;uid=sa;pwd=123456;database=ordertest;"
    },
    "RabbitMQ": {
        "HostName": "172.16.20.157",
        "VirtualHost": "/",
        "UserName": "admin",
        "Password": "admin",
        "Port": "5672"
    } 
}


发布事件/消息


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

public class PublishController : Controller
{
    private readonly ICapPublisher _capBus;
    private readonly OrderDbContext _context;
    public OrderController(ICapPublisher capBus, OrderDbContext context)
    {
        _capBus = capBus;
        _context = context;
    }
    public IActionResult CreateOrder()
    {
        return View();
    }
    [HttpPost]
    public IActionResult Submit(Order order)
    {
        using var tran = _context.Database.BeginTransaction(_capBus);
        try
        {
            _context.Order.Add(order);
            _context.SaveChanges();
            //发送消息
            _capBus.Publish("order.create",order);
            tran.Commit();
            return Redirect("/home/index");
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            tran.Rollback();
            return BadRequest(e.Message);
        }
    }
}


订阅事件/消息


在 Controller 中:

如果是在Controller中,直接添加[CapSubscribe("")] 来订阅相关消息。

public class ConsumerController : Controller
{
    private readonly OrderDbContext _context;
    public ConsumerController( OrderDbContext context)
    {
        _context = context;
    }
    [CapSubscribe(name:"order.create")] //这个要与publisher 方法中的name要一致
    public void OrderCreateConsumer(Order order)
    {
        //减库存
        var product = _context.Product.FirstOrDefault(p=>p.Id==order.ProductId);
        product.Stock -= order.Quantity;
        _context.SaveChanges();
    }
}


在 xxxService中:

如果你的方法没有位于Controller 中,那么你订阅的类需要继承 ICapSubscribe,然后添加[CapSubscribe("")]标记:

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


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

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<ISubscriberService,SubscriberService>();
}


结束了,怎么样,是不是很简单?


异常解决


RabbitMQ : SubscriberNotFoundException #63

es() 中注入你的 ISubscriberService 类

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<ISubscriberService,SubscriberService>();
}


结束了,怎么样,是不是很简单?

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
相关文章
|
8天前
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
30 5
|
2月前
|
存储 开发框架 JSON
ASP.NET Core OData 9 正式发布
【10月更文挑战第8天】Microsoft 在 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9,此版本与 .NET 8 的 OData 库保持一致,改进了数据编码以符合 OData 规范,并放弃了对旧版 .NET Framework 的支持,仅支持 .NET 8 及更高版本。新版本引入了更快的 JSON 编写器 `System.Text.UTF8JsonWriter`,优化了内存使用和序列化速度。
|
26天前
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
38 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
16天前
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
24 3
|
29天前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
39 5
|
3月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
3月前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
111 3
|
2月前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架
|
2月前
|
JavaScript 调度
Vue事件总线(EventBus)使用指南:详细解析与实战应用
Vue事件总线(EventBus)使用指南:详细解析与实战应用
92 1
|
4月前
|
JavaScript
Vue学习之--------全局事件总线(2022/8/22)
这篇文章介绍了Vue中全局事件总线(GlobalEventBus)的概念和使用方法,它允许不同组件之间进行通信。文章通过图解和代码实例详细解释了如何安装全局事件总线、在组件中接收和提供数据,以及如何在组件销毁前解绑事件,以避免潜在的内存泄漏问题。
Vue学习之--------全局事件总线(2022/8/22)