如何使用Azure.Messaging.ServiceBus实现Azure Service Bus同步发送消息
问题描述
我计划为现有应用搭建一套监控服务,该服务会根据主Web应用的运行事件,检查Azure Service Bus队列中的消息。近期遇到的问题如下:
查阅官方文档后发现,绝大多数示例都采用异步代码实现,这本身并无问题。类似Entity Framework会提供_context.Save()与_context.SaveAsync()两种方法供选择,但我未找到Azure.Messaging.ServiceBus包支持同步调用的示例,同时我也清楚同步运行异步代码属于不良实践。
我需要使用同步方案的原因很简单:当前使用的Web应用较为老旧,存量代码量极大,将所有相关方法改写为异步需要耗费极长的时间,因此我希望能以同步方式向Service Bus发送消息。我当前使用的是Azure.Messaging.ServiceBus包,希望将如下异步调用逻辑改为同步实现:
sender = client.CreateSender(queueName); await sender.SendMessagesAsync(messageBatch);
解决方案
Azure.Messaging.ServiceBus包官方未提供原生同步API,存量老项目兼容场景可以通过阻塞异步任务的方式实现同步调用:
通用实现方案
// 创建Sender的逻辑本身是同步方法,无需调整 sender = client.CreateSender(queueName); // 阻塞等待异步方法执行完成,GetAwaiter().GetResult()可保留原始异常堆栈,优于直接使用.Result sender.SendMessagesAsync(messageBatch).GetAwaiter().GetResult();
.NET Framework 传统ASP.NET项目兼容方案
如果你的项目是基于.NET Framework的传统ASP.NET项目,存在同步上下文限制,直接调用容易触发死锁,建议采用以下写法规避:
sender = client.CreateSender(queueName); // 把异步调用放到线程池执行,规避同步上下文死锁问题 Task.Run(() => sender.SendMessagesAsync(messageBatch)).Wait();
注意:以上方案仅作为老项目临时兼容手段,同步阻塞会降低IO吞吐量,后续迭代建议逐步把相关业务链路改造为异步实现。
内容的提问来源于stack exchange,提问作者Vladimir
相关产品推荐
相关产品推荐

