MASA Framework -- EventBus入门与设计( 三 )

SagaEventBus支持Saga模式

MASA Framework -- EventBus入门与设计

文章插图
具体是怎么做呢?
[EventHandler(1, IsCancel = true)]public void CancelSendAwardByRegister(RegisterUserEvent @event){    _logger?.LogDebug("-----------{Account} 注册成功,发放奖励失败 {Message}-----------", @event.Account, "发放奖励补偿");}
当发送奖励出现异常时,则执行补偿机制 , 执行顺序为 (2 - 1) > 0 , 由于目前仅存在一个Order为1的Handler,则执行奖励补偿后退出
但对于部分不需要执行失败但不需要执行回退的方法 , 我们可以修改 FailureLevels 确保不会因为当前方法的异常而导致执行补偿机制
[EventHandler(3, FailureLevels = FailureLevels.Ignore)]public void SendNoticeByRegister(RegisterUserEvent @event){    _logger?.LogDebug("-----------{Account} 注册成功 {Message}-----------", @event.Account, "发送邮件提示注册成功");    //todo: 编写发送注册通知等}源码解读EventHandler
  • FailureLevels: 失败级别, 默认: Throw
    • Throw:发生异常后 , 依次执行Order小于当前Handler的Order的取消动作,比如:Handler顺序为 1、2、3,CancelHandler为 1、2、3 , 如果执行 Handler3 异常,则依次执行 2、1
    • ThrowAndCancel:发生异常后,依次执行Order小于等于当前Handler的Order的取消动作,比如:Handler顺序为 1、2、3 , CancelHandler为 1、2、3,如果执行 Handler3 异常,则依次执行 3、2、1
    • Ignore:发生异常后,忽略当前异常(不执行取消动作),继续执行其他Handler
  • Order: 执行顺序,默认: int.MaxValue,用于控制当前方法的执行顺序
  • EnableRetry: 当Handler异常后是否启用重试, 默认: false
  • RetryTimes: 重试次数,当出现异常后执行多少次重试, 需开启重试配置
  • IsCancel: 是否是补偿机制,默认: false
Middleware
  • SupportRecursive: 是否支持递归 (嵌套), 默认: true
    • 部分中间件仅在最外层被触发一次,像TransactionMiddleware 就是如此,但也有很多中间件是需要被多次执行的,比如ValidatorMiddleware,每次发布事件时都需要验证参数是否正确
  • HandleAsync(TEvent @event, EventHandlerDelegate next): 处理程序,通过调用 next() 使得请求进入下一个Handler
IEventHandler 与 ISagaEventHandler
  • HandleAsync(TEvent @event): 提供事件的Handler
  • CancelAsync(TEvent @event): 提供事件的补偿Handler
与EventHandler功能类似,提供基本的Handler以及补偿Handler , 推荐使用EventHandler的方式使用
TransactionMiddleware提供事务中间件,当EventBus与UoW以及Masa提供的Repository来使用时,当存在待提交的数据时,会自动执行保存并提交,当出现异常后,会执行事务回滚,无需担心脏数据入库
性能测试与市面上使用较多的MeidatR作了对比,结果如下图所示:
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19043.1023 (21H1/May2021Update)11th Gen Intel Core i7-11700 2.50GHz, 1 CPU, 16 logical and 8 physical cores.NET SDK=7.0.100-preview.4.22252.9[Host]     : .NET 6.0.6 (6.0.622.26707), X64 RyuJIT DEBUGJob-MHJZJL : .NET 6.0.6 (6.0.622.26707), X64 RyuJIT
Runtime=.NET 6.0  IterationCount=100  RunStrategy=ColdStart
MethodMeanErrorStdDevMedianMinMaxAddShoppingCartByEventBusAsync124.80 us346.93 us1,022.94 us8.650 us6.500 us10,202.4 usAddShoppingCartByMediatRAsync110.57 us306.47 us903.64 us7.500 us5.300 us9,000.1 us根据性能测试我们发现,EventBus与MediatR性能差距很小,但EventBus提供的功能却要强大的多
常见问题
  1. 按照文档操作 , 通过EventBus发布事件后,对应的Handler并没有执行 , 也没有发现错误?
①. EventBus.PublishAsync(@event) 是异步方法,确保等待方法调用成功,检查是否出现同步方法调用异步方法的情况②. 注册EventBus时指定程序集集合, Assembly被用于注册时获取并保存事件与Handler的对应关系
var assemblies = new[]{    typeof(UserHandler).Assembly};builder.Services.AddEventBus(assemblies);

推荐阅读