ServiceBusClient 发送消息前必须确认连接字符串具有 Send 权限,否则会因 UnauthorizedAccessException 或 401 错误失败;发送需通过 ServiceBusSender(由 client.CreateSender() 创建)调用 SendMessageAsync,且消息须封装为 ServiceBusMessage。

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 实例










