Brighter 与 Azure 服务总线集成指南

Azure 服务总线简介  

Azure 服务总线是一个完全托管的企业级消息代理,可促进云环境和混合环境中应用程序与服务之间的可靠通信。它支持消息队列(点对点通信)和发布-订阅主题(向多个消费者广播),非常适合解耦分布式系统。通过 Paramore.Brighter.MessagingGateway.AzureServiceBus 包,Brighter 提供了与 Azure 服务总线的一流集成,使 .NET 应用程序中的命令/事件路由更加无缝。

要求  

Brighter 回顾  

在继续 Azure 服务总线配置之前,先回顾一下我们已知的 Brighter 知识。

请求(命令/事件)

使用 IRequest 定义消息:  

public class Greeting() : Event(Guid.NewGuid())
{
    public string Name { get; set; } = string.Empty;
}
  • 命令:单接收者操作(例如 SendEmail)。  
  • 事件:广播通知(例如 OrderShipped)。

消息映射器  

在 Brighter 消息与应用程序对象之间转换:  

public class GreetingMapper : IAmAMessageMapper<Greeting>
{
    public Message MapToMessage(Greeting request)
    {
        var header = new MessageHeader();
        header.Id = request.Id; 
        header.TimeStamp = DateTime.UtcNow;
        header.Topic = "greeting.topic"; // 目标主题
        header.MessageType = MessageType.MT_EVENT;

        var body = new MessageBody(JsonSerializer.Serialize(request));
        return new Message(header, body);
    }

    public Greeting MapToRequest(Message message)
    {
        return JsonSerializer.Deserialize<Greeting>(message.Body.Bytes)!;
    }
}

请求处理器  

处理传入消息:  

public class GreetingHandler(ILogger<GreetingHandler> logger) : RequestHandler<Greeting>
{
    public override Greeting Handle(Greeting command)
    {
        logger.LogInformation("你好 {Name}", command.Name);
        return base.Handle(command);
    }
}

使用 Azure 服务总线配置 Brighter

 
1. 连接设置  

使用 Azure 凭据提供程序进行安全认证:  

var connection = new ServiceBusVisualStudioCredentialClientProvider(".servicebus.windows.net");

或使用连接字符串:  

var connection = new ServiceBusConnectionStringClientProvider("<Your-Connection-String>");

2. Azure 服务总线订阅  

订阅队列/主题:  

.AddServiceActivator(opt =>
{
    opt.Subscriptions = [
        new AzureServiceBusSubscription<Greeting>(
            new SubscriptionName("greeting-subscription"), // 可选
            new ChannelName("greeting-queue"), // 队列名称
            new RoutingKey("greeting-topic"), // 主题名称
            bufferSize: 2)
    ];
    opt.ChannelFactory = new AzureServiceBusChannelFactory(new AzureServiceBusConsumerFactory(connection, false));
})

3. Azure 服务总线生产者配置  

发布事件到主题:  

.UseExternalBus(new AzureServiceBusProducerRegistryFactory(connection, new[]
{
    new AzureServiceBusPublication
    {
        Topic = new RoutingKey("greeting-topic"),
        MakeChannels = OnMissingChannel.Create
    }
}).Create());

4. 死信队列(DLQ)  

启用 DLQ 处理有毒消息:  

opt.Subscriptions = [
    new AzureServiceBusSubscription<Greeting>(
        subscriptionName: new SubscriptionName("greeting-subscription"),
        channelName: new ChannelName("greeting-queue"),
        routingKey: new RoutingKey("greeting-topic"),
        subscriptionConfiguration: new AzureServiceBusSubscriptionConfiguration
        {
            DeadLetteringOnMessageExpiration = true // 启用 DLQ
        },
        bufferSize: 2
    )
];

Azure 服务总线会自动将过期或失败的消息移动到 DLQ 以供检查。

结论

 将 Brighter 与 Azure 服务总线集成可在 .NET 应用程序中实现稳健、可扩展的消息传递。通过利用 Azure 的托管基础设施和 Brighter 的抽象层,您可以:  

  •  通过发布-订阅模式解耦服务。  
  •  确保消息顺序和可靠性。  
  • 通过 DLQ 简化错误处理。  

在生产环境中使用时,始终根据 Brighter 的最新文档验证 Azure 服务总线配置。

参考  

// See https://aka.ms/new-console-template for more information
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Paramore.Brighter;
using Paramore.Brighter.Extensions.DependencyInjection;
using Paramore.Brighter.MessagingGateway.AzureServiceBus;
using Paramore.Brighter.MessagingGateway.AzureServiceBus.ClientProvider;
using Paramore.Brighter.ServiceActivator.Extensions.DependencyInjection;
using Paramore.Brighter.ServiceActivator.Extensions.Hosting;
using Serilog;


Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .Enrich.FromLogContext()
    .WriteTo.Console()
    .CreateLogger();


var host = new HostBuilder()
    .UseSerilog()
    .ConfigureServices((_, services) =>
    {
        var connection = new ServiceBusVisualStudioCredentialClientProvider(".servicebus.windows.net");

        services
            .AddHostedService<ServiceActivatorHostedService>()
            .AddServiceActivator(opt =>
            {
                opt.Subscriptions = [
                    new AzureServiceBusSubscription<Greeting>(
                        new SubscriptionName("greeting-subscription"), // Optional
                        new ChannelName("greeting-queue"), // Queue name
                        new RoutingKey("greeting-topic"), // Topic Name
                        subscriptionConfiguration: new AzureServiceBusSubscriptionConfiguration{
                            DeadLetteringOnMessageExpiration = true // Enablin DLQ
                        },
                        bufferSize: 2)
                ];
                opt.ChannelFactory = new AzureServiceBusChannelFactory(new AzureServiceBusConsumerFactory(connection, false));
            })
            .AutoFromAssemblies()
            .UseExternalBus(new AzureServiceBusProducerRegistryFactory(connection, new[]
            {
                new AzureServiceBusPublication
                {
                    Topic = new RoutingKey("greeting-topic"),
                    MakeChannels = OnMissingChannel.Create
                }
            }).Create());
    })

    .Build();

_ = host.RunAsync();


while (true)
{
    await Task.Delay(TimeSpan.FromSeconds(10));
    Console.Write("Say your name (or q to quit): ");
    var name = Console.ReadLine();

    if (string.IsNullOrEmpty(name))
    {

        continue;
    }


    if (name == "q")
    {
        break;
    }

    var process = host.Services.GetRequiredService<IAmACommandProcessor>();
    process.Post(new Greeting { Name = name });
}

await host.StopAsync();



public class Greeting() : Event(Guid.NewGuid())
{
    public string Name { get; set; } = string.Empty;
}

public class GreetingMapper : IAmAMessageMapper<Greeting>
{
    public Message MapToMessage(Greeting request)
    {
        var header = new MessageHeader();
        header.Id = request.Id;
        header.TimeStamp = DateTime.UtcNow;
        header.Topic = "greeting.topic";
        header.MessageType = MessageType.MT_EVENT;

        var body = new MessageBody(JsonSerializer.Serialize(request));
        return new Message(header, body);
    }

    public Greeting MapToRequest(Message message)
    {
        return JsonSerializer.Deserialize<Greeting>(message.Body.Bytes)!;
    }
}

public class GreetingHandler(ILogger<GreetingHandler> logger) : RequestHandler<Greeting>
{
    public override Greeting Handle(Greeting command)
    {
        logger.LogInformation("Hello {Name}", command.Name);
        return base.Handle(command);
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值