文章目录
- 1.集成事件
- 1.1 定义
- 1.2 集成事件工作原理
- 1.3 总结
- 2.使用RabbitMQ来实现EventBus
- 2.1 RabbitMQ安装
- 2.2 CAP框架实现RabbitMQ
- 2.2.1 CAP框架实现架构
- 2.2.2 CAP框架实现原理
- 3.MediatR
- 3.1 使用Mediator实现命令查询职责分离模式(CQRS)
- 3.1.1 核心对象
- 3.2 处理领域事件
- 3.2.1 核心对象
1.集成事件
1.1 定义
集成事件目的是为了实现系统的集成,主要是用来在系统多个微服务之间相互传递事件,实现方式有两种
- 发布、订阅通过EventBus方式
- 通过观察者模式,由观察者将事件发给关注事件的人
1.2 集成事件工作原理
// 定义集成事件,命名:事件名称+IntergationEvent
public class OrderCreateIntergationEvent
{public OrderCreatedIntergrationEvent(long orderId) => OrderId = orderId;public long OrderId {get;}
}// 发布
public class OrderCreateDomainEventHandler : IDomainEventHandler<OrderCreateDomainEvent>
{// 发送集成事件的接口框架ICapPublisher _capPublisher;public OrderCreateDomainEventHandler(ICapPublisher capPublisher){_capPublisher = capPublisher;}public async Task Handle(OrderCreatedDomainEvent notification,CancellationToken cancelationToken){// 将名称为 "OrderCreated"的集成事件发送出去await _capPublisher.PublishAsync("OrderCreated",new OrderCreatedIntergrationEvent(notification.Order.Id))}
}// 订阅服务
public class SubscriberService : ISubscriberService,ICapSubscribe
{IMediator _mediator;public SubscriberService(IMediator mediator){_mediator = mediator;}[CapSubscribe("OrderPaymentSuccessed")]public void OrderPaymentSuccessed(OrderPaymentSuccessedIntergrationEvent envent){// TODO...}}
1.3 总结
- 集成事件是跨服务的领域事件
- 集成事件一般由领域事件驱动触发
- 不通过事务来处理集成事件(实现最终一致性)
- 仅在必要的情况下定义和使用集成事件
2.使用RabbitMQ来实现EventBus
2.1 RabbitMQ安装
进入RabbitMQ网站下载
RabbitMQ下载地址
2.2 CAP框架实现RabbitMQ
2.2.1 CAP框架实现架构
CAP框架实际是实现了OutBox的设计模式
OutBox设计模式是在每一个微服务中,比如微服务A的数据库A中建立两张表。一张publish事件表和一张receive事件表,这两张事件表用来记录微服务A发出和接收到的事件。当需要发出事件时,会把事件的存储逻辑和业务逻辑的事务合并,在同一个事务里提交,也就意味着当业务逻辑提交成功时,事件表里面的事件是一定存在的,它是与业务逻辑的事务是强绑定的,这就保证了所发出的事件是与业务逻辑一致的。接下来就是由组件负责将事件表中的事件全部发送到EventBus中,比如RabbitMQ消息队列中,由接受方订阅。
对于订阅事件,设计模式是同理。当应用程序从消息队列中获取到消息时,就会将这些消息持久化到数据库中的receive事件表中,这样就可以在本地进行事件的处理、失败重试等操作,这都是由CAP框架来完成。
// 演示代码
private IDbContextTransaction _currentTransaction;public Task<IDbContextTransaction> BeginTransactionAsync()
{if(_currentTransaction == null) return null;// 将业务存储放在同一个事务中,使得事务提交或回滚时,事件与业务逻辑的存取都是一致的_currentTransaction = DataBase.BeginTransaction(_capBus,autoCommit:false);return Task.FromResult(_currentTransaction);
}// 服务配置
public static IServiceCollection AddEventBus(this IServiceCollection services,IConfiguration configuration)
{services.AddTransient<ISubscriberService,SubscriberService>();services.AddCap(options =>{// 基于DomainContext实现EventBusoptions.UseEntityFramework<DomainContext>();// 使用RabbitMQ作为消息队列的存储options.UseRabbitMQ(options =>{// RabbitMQ配置configuration.GetSection("RabbitMQ").Bind(options);});};return services;
}
2.2.2 CAP框架实现原理
- 事件表
- 事务控制
3.MediatR
3.1 使用Mediator实现命令查询职责分离模式(CQRS)
3.1.1 核心对象
- IMediator
- IRequest、IRequest< T>
- IRequestHandler< in TRquest,TResponse>
async static Task Main(string[] args)
{var services = new ServiceCollection();services.AddMediatR(typeof(Program).Assembly);var serviceProvider = services.BuildServiceProvider();var mediator = serviceProvider.GetService<IMediator>();await mediator.Send(new MyCommand{CommandName= "cmd01"});
}class MyCommand : IRequest<long>
{public string CommandName {get;set;}
}// 命令处理器定义
class MyCommandHandler : IRequestHandler<MyCommand,long>
{public Task<long> Handle(MyCommand request,CancellationToken cancelationToken){ConsoleWriteLine($@"MyCommandHandler 执行命令{request.CommandName}");return Task.FromResult(10L);}
}
通过中介者模式(MediatoR),可以将命令的构造和命令的处理分离开
3.2 处理领域事件
3.2.1 核心对象
- IMediator
- INotification
- INotificationHandler< in TNotification>
async static Task Main(string[] args)
{var services = new ServiceCollection();services.AddMediatR(typeof(Program).Assembly);var serviceProvider = services.BuildServiceProvider();var mediator = serviceProvider.GetService<IMediator>();//await mediator.Publish(new MyEvent{EventName= "Event01"});Console.WriteLine("Hello World");
}class MyEvent : INotification
{public string EventName {get;set;}
}internal class MyEventHandler : INotificationHandler<MyEvent>
{public Task Handle(MyEvent notification,CancellationToken cancelationToken){Console.WriteLine($"MyEventHandle执行:{notification.EventName}");return Task.CompletedTask;}
}internal class MyEventHandler2 : INotificationHandler<MyEvent>
{public Task Handle(MyEvent notification,CancellationToken cancellationToken){Console.WriteLine($"MyEventHandle2执行:{notification.EventName}");return Task.CompletedTask;}
}
INotification可以注册多个,是一对多的关系,借助此我们可以对领域事件定义多个处理器