项目

微服务方案:分布式事件

您必须拥有ABP商业版或更高级别的许可证才能创建微服务解决方案。

微服务解决方案模板采用分布式事件总线机制实现微服务间的异步通信。事件总线采用发布-订阅模式,允许微服务在不感知彼此的情况下进行通信,这有助于解耦微服务并使其更加独立。

在微服务解决方案模板中,使用RabbitMQ作为消息代理来管理这些事件。该功能通过Volo.Abp.EventBus.RabbitMQ包实现,该包提供了使用RabbitMQ发布和订阅事件所需的实现。此设置已集成到微服务解决方案模板中,并应用于微服务/应用项目。您可以在相关项目的appsettings.json文件中修改RabbitMQ配置,默认配置如下:

  "RabbitMQ": {
    "Connections": {
      "Default": {
        "HostName": "localhost"
      }
    },
    "EventBus": {
      "ClientName": "ProjectName_MicroserviceName",
      "ExchangeName": "ProjectName"
    }
  }

ExchangeName是用于发布和订阅事件的交换机名称。应用程序中的不同微服务应使用相同的交换机名称以相互通信。ClientName是用于连接RabbitMQ的客户端名称。建议使用微服务名称作为客户端名称。这样,当消息发布时,订阅该交换机的所有客户端都会收到消息。

发布事件

要发布事件,请注入IDistributedEventBus服务并调用PublishAsync方法。PublishAsync方法以事件对象作为参数。以下是发布事件的示例:

public class MyService : ITransientDependency
{
    private readonly IDistributedEventBus _distributedEventBus;

    public MyService(IDistributedEventBus distributedEventBus)
    {
        _distributedEventBus = distributedEventBus;
    }
    
    public virtual async Task ChangeStockCountAsync(Guid productId, int newCount)
    {
        await _distributedEventBus.PublishAsync(
            new StockCountChangedEto
            {
                ProductId = productId,
                NewCount = newCount
            }
        );
    }
}

订阅事件

要订阅事件,请实现IDistributedEventHandler<TEvent>接口。以下是订阅事件的示例:

public class MyHandler : IDistributedEventHandler<StockCountChangedEto>, ITransientDependency
{
    public async Task HandleEventAsync(StockCountChangedEto eventData)
    {
        var productId = eventData.ProductId;
    }
}

发件箱/收件箱模式

发件箱/收件箱模式确保消息安全可靠地传递。发件箱模式在将消息发送到消息代理之前,将其存储在数据库中。收件箱模式在处理消息之前将其存储在数据库中,确保在发生故障时消息不会丢失。微服务解决方案模板使用发件箱/收件箱模式来确保消息的安全可靠传递。您可以在分布式事件总线文档中了解更多关于发件箱/收件箱模式的信息。

您可以在相关项目的Module类中查看发件箱/收件箱模式的配置。默认配置如下:

private void ConfigureDistributedEventBus()
{
    Configure<AbpDistributedEventBusOptions>(options =>
    {
        options.Inboxes.Configure(config =>
        {
            config.UseDbContext<MicroserviceDbContext>();
        });

        options.Outboxes.Configure(config =>
        {
            config.UseDbContext<MicroserviceDbContext>();
        });
    });
}

使用发件箱/收件箱模式的一个缺点是,由于消息存储在数据库中,每个微服务都需要自己的数据库架构。如果您使用EntityFrameworkCore并希望在不同微服务间共享同一数据库连接,这可能会带来问题。拥有两个不同数据库架构(DbContext)且包含相同表名时,将导致冲突。


在本文档中