C# Azure Service Bus发送消息方法 C#如何使用Service Bus队列和主题

来源:这里教程网 时间:2026-02-21 17:40:48 作者:

ServiceBusClient 发送消息前必须确认连接字符串权限

ServiceBusClient
发送消息失败,十有八九是连接字符串没开“Send”权限。Azure 门户里生成的连接字符串默认只含“Listen”,哪怕你只是发消息,也得手动进“Shared access policies”新建一个带
Send
(或
Manage
)权限的策略,再拿它的连接字符串。

常见错误现象:

UnauthorizedAccessException
401 Unauthorized
,但堆栈里不直接提权限——它藏在底层 HTTP 响应里。

队列场景:连接字符串只需
Send
权限
主题场景:同样只需
Send
,不用
Manage
(除非你要动态创建订阅)
本地开发调试时,别用 RootManageSharedAccessKey 的完整连接字符串,容易误提交到代码库

发送到队列用 ServiceBusSender.SendMessageAsync,不是 SendAsync

ServiceBusSender
是发送入口,不是
ServiceBusClient
直接发。调用链必须是:
ServiceBusClient
CreateSender("queue-name")
SendMessageAsync
。写成
client.SendAsync(...)
会编译不过——这个方法根本不存在。

示例关键片段:

var client = new ServiceBusClient(connectionString);
var sender = client.CreateSender("myqueue");
await sender.SendMessageAsync(new ServiceBusMessage("hello"));
每条消息封装为
ServiceBusMessage
,不能直接传 string 或 byte[]
若需设置 TTL、SessionId、CorrelationId 等,都在
ServiceBusMessage
构造后赋值属性
同一个
ServiceBusSender
实例可复用,但别跨线程共用未加锁的实例(SDK 内部已做线程安全处理,但高并发下仍建议按作用域创建)

发到主题要指定主题名,订阅名由接收方控制

主题(Topic)和队列(Queue)的发送 API 完全一致,区别只在

CreateSender
的参数:传主题名,不是订阅名。订阅(Subscription)是接收端概念,发送方完全感知不到。

例如发到主题

orders-topic

var sender = client.CreateSender("orders-topic"); // 不是 "orders-topic/subscriptions/new-orders"
await sender.SendMessageAsync(new ServiceBusMessage(JsonSerializer.Serialize(order)));
主题支持通配符订阅(如
orders-*
),但发送方无需、也不能指定匹配逻辑
若消息需要路由到特定订阅,得靠
Rule
+
Message.UserProperties
ApplicationProperties
配合筛选器,不是靠发送路径
主题本身不存消息,消息进入主题后立刻分发到所有匹配的订阅;所以发送成功 ≠ 订阅端收到,得单独查订阅的活跃消息数

生产环境必须处理 MessageException 和 ServiceBusException

网络抖动、配额超限、消息体超 256KB(标准层)都会抛

ServiceBusException
,而
MessageException
多见于序列化失败(比如传了不可序列化的对象)。不捕获这些异常,会导致消息静默丢失或应用崩溃。

推荐用
try/catch (ServiceBusException ex) when (ex.Reason == ServiceBusFailureReason.ServiceTimeout)
做重试
MessageSizeExceeded
类异常,必须提前校验
ServiceBusMessage.Body
长度,SDK 不会在发送前主动检查
不要依赖
sender.DisposeAsync()
清理连接——它只释放本地资源;连接池由
ServiceBusClient
统一管理,应优先复用 client 实例
实际用起来最易忽略的是:主题发送和队列发送代码一模一样,差别全在 Azure 资源命名和后台配置上。很多人卡在“发了但收不到”,结果发现是订阅没建、或筛选器写错了条件、或订阅被手动禁用了。

相关推荐