在分布式系统架构中,消息队列是处理服务间异步通信、流量削峰和故障隔离的关键组件。Azure Service Bus作为微软Azure云平台上的全托管消息代理服务,提供了队列(Queue)和主题订阅(Topic/Subscription)两种消息实体,同时内置了重复检测、会话、事务和死信队列等功能,非常适合构建企业级.NET应用。本文将详细演示如何从零开始在.NET项目中集成Azure Service Bus,完成消息的可靠收发。

环境准备与核心概念
在开始编码之前,需要先理解Azure Service Bus的几个核心概念。命名空间(Namespace)是服务总线资源的容器,每个命名空间拥有独立的连接字符串和访问密钥,所有队列和主题都创建在命名空间下。队列(Queue)提供一对一的先进先出消息传递,一个发送方将消息放入队列,一个接收方从中取出并处理,适用于简单的任务分发。主题订阅(Topic/Subscription)则支持一对多的广播模式,发布者将消息发送到主题,多个订阅可以各自接收一份消息副本,并能通过过滤规则选择性地接收符合条件的消息,适合事件驱动的微服务架构。
环境准备的第一步是在Azure门户中创建Service Bus命名空间。选择标准或高级定价层,因为基础层不支持主题和某些高级特性。创建完成后,在命名空间的“共享访问策略”中添加一个策略,例如RootManageSharedAccessKey,并复制主连接字符串。该连接字符串会作为.NET应用与服务总线通信的凭证。接下来,在.NET项目中安装官方客户端库,通过NuGet命令安装Azure.Messaging.ServiceBus包。该库基于AMQP协议,支持异步流式处理,并已针对云环境优化了连接池和重试逻辑。以下代码展示了如何初始化客户端并创建发送器:
var connectionString = "<your-connection-string>"; var queueName = "orders"; // 创建ServiceBusClient实例,建议作为单例注入 await using var client = new ServiceBusClient(connectionString); // 创建消息发送器 await using var sender = client.CreateSender(queueName);
ServiceBusClient是客户端连接的管理器,应尽可能复用,避免频繁创建和销毁连接。在ASP.NET Core应用中,可通过依赖注入将其注册为单例服务。发送器则可以根据需要创建,用完即释放。队列或主题的名称需要在发送前确保已经存在于命名空间中,否则会抛出异常,当然也可以使用管理客户端在代码中动态创建实体。
在.NET中发送与接收消息
发送消息时,需要构造ServiceBusMessage对象。除了常规字符串或字节数组作为消息体,还可以附加自定义属性和消息ID,用于去重或路由。下面的示例展示了如何发送一条JSON格式的订单消息,并设置消息ID和会话ID:
var orderJson = JsonSerializer.Serialize(new { OrderId = 1024, Amount = 99.9m });
var message = new ServiceBusMessage(orderJson)
{
MessageId = Guid.NewGuid().ToString(),
SessionId = "order-session-1024",
ContentType = "application/json"
};
message.ApplicationProperties.Add("Priority", "High");
await sender.SendMessageAsync(message);
Console.WriteLine("Message sent.");
MessageId用于标识消息唯一性,配合队列或主题的重复检测功能可以保证一定时间窗口内不会重复投递同一消息。SessionId则用于会话,保证同一会话内的消息按顺序由同一个接收者处理。发送完成后,可以从Azure门户查看队列活动消息数是否增加,验证消息是否入队。
接收消息有两种主要方式:使用ServiceBusReceiver手动拉取,或使用ServiceBusProcessor实现事件驱动的推送式消费。生产中更推荐ServiceBusProcessor,它能自动处理并发、连接恢复和回调。下面的代码展示了注册消息处理函数和错误处理函数,并启动处理器:
await using var processor = client.CreateProcessor(queueName, new ServiceBusProcessorOptions
{
MaxConcurrentCalls = 2,
AutoCompleteMessages = false
});
processor.ProcessMessageAsync += async args =>
{
var body = args.Message.Body.ToString();
Console.WriteLine($"Received: {body}");
// 业务处理成功后手动完成消息
await args.CompleteMessageAsync(args.Message);
};
processor.ProcessErrorAsync += args =>
{
Console.WriteLine($"Error: {args.Exception.Message}");
return Task.CompletedTask;
};
await processor.StartProcessingAsync();
Console.WriteLine("Press any key to stop...");
Console.ReadKey();
await processor.StopProcessingAsync();
这里将AutoCompleteMessages设为false,代表需要手动调用CompleteMessageAsync确认消息已被成功处理。如果处理过程中出现异常,可以不完成消息,消息会被重新投递,从而达到重试效果。Azure Service Bus默认有最大传递次数,超过次数后消息将移入死信队列。通过合理控制并发数MaxConcurrentCalls,可以平衡吞吐量与资源消耗。
在ASP.NET Core后台服务中,可以将ServiceBusProcessor托管为IHostedService,使应用程序启动时自动开始监听,关闭时优雅停止。此外,利用CancellationToken可以响应容器化环境的终止信号。这种模式能够完全融入云原生应用的部署流程,实现7x24小时高可用接收。
高级特性与生产实践
死信队列(DLQ)是Azure Service Bus为保障消息不丢失而设计的重要机制。当消息达到最大传递次数后仍未成功处理,或消息TTL(生存时间)过期,系统会自动将其移入DLQ。开发者可以通过在队列或订阅上启用DeadLetteringOnMessageExpiration,并在处理器中捕获异常后主动将消息送入DLQ,例如:
processor.ProcessMessageAsync += async args =>
{
try
{
// 业务逻辑
await args.CompleteMessageAsync(args.Message);
}
catch (BusinessException ex)
{
// 将无法处理的消息主动送入死信
await args.DeadLetterMessageAsync(args.Message, "BusinessError", ex.Message);
}
};
这样,失败的消息不会丢失,后续可以单独创建一个DLQ监控应用,从死信队列中提取消息进行分析、重试或人工干预。这个特性在订单处理和金融对账场景中尤其关键,避免了因程序瑕疵导致的业务数据黑洞。
消息会话(Session)是实现FIFO严格顺序的利器。当需要为某个实体(如订单ID)的所有消息保证顺序处理时,可以启用会话,并在接收端使用ServiceBusSessionProcessor。同一会话ID的消息会被同一个接收者按序拉取,且在一个会话的消息被处理期间,该会话不会分配给其他接收者,从而天然避免并发串行干扰。处理器配置中设置SessionIdleTimeout可以自动释放空闲会话,提升资源利用效率。对于超时业务,若长时间无消息,会话会被自动关闭,下一条同SessionId消息进入时会创建新会话。
重复检测是防止消息重入的保护伞。在生产环境中,由于网络抖动或重试逻辑,同一个MessageId的消息可能被两次发送。启用队列的重复检测窗口(如5分钟)后,服务端会检查MessageId,在该时间窗口内拒绝重复的消息。这简化了消费者端的幂等性实现。此外,Azure Service Bus支持计划投递,即指定消息在将来的某个时间点才被消费者可见,常用于延迟任务调度。发送时设置ScheduledEnqueueTime即可。在ASP.NET Web应用中,常常将耗时操作通过消息异步化,并结合计划投递实现定时回调,极大降低了数据库轮询压力。
性能方面,建议在.NET 6及更高版本中使用ServiceBusClient的单例模式,并利用异步方法释放线程避免阻塞。当需要批量发送消息时,可使用ServiceBusSender.CreateMessageBatchAsync()将多条消息打包一次发送,显著减少网络往返。同时,在处理器中注意异常分类处理,避免频繁触发内部重试导致消息积压。通过Azure Monitor观察队列长度、死信数量和操作延迟,可以主动调整SKU和并发数,维持系统弹性。只要遵循这些实践,Azure Service Bus就能成为.NET系统中最稳固的异步通信底座。
Azure_Service_Bus.NET消息队列修改时间:2026-08-12 12:32:31