我正在尝试在 Azure 中构建一个简单的 Web API REST 服务,并在后端使用服务总线队列工作线程。我可以很好地从 Web API 向工作人员发送一条消息。然而,我试图发送更多消息只是为了看看一切如何运作。所以,我创建了一个简单的控制器,如下所示:
for (int i = 0; i < 100; i++)
{
var msg = new BrokeredMessage("Ping");
BioConnector.QueueConnector.OrdersQueueClient.Send(msg);
}
当我调用控制器时,我只收到工作人员收到的大约 1/2 左右的消息。剩下的好像都被放弃了。
我在使用here发布的示例代码时只获取大约一半的消息时遇到问题,所以我编写了自己的测试代码。我已经尝试过超过 100 个队列消息,并且始终具有 100% 的发送/接收奇偶校验。也许您的代码也有类似的问题。
在 app.config 中,将其更改为您自己提供的值:
<appSettings>
<add key="Microsoft.ServiceBus.ConnectionString" value="Endpoint=sb://blahblah.servicebus.windows.net/;SharedSecretIssuer=owner;SharedSecretValue=pDk0b....=" />
</appSettings>
添加这些 using 指令:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Messaging;
using System.Configuration;
using System.Threading;
将代码方法更改为以下:
class Program
{
static void Main(string[] args)
{
string connectionString = ConfigurationSettings.AppSettings["Microsoft.ServiceBus.ConnectionString"];
var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString);
QueueDescription queueDesc = new QueueDescription("TestQueue");
if (!namespaceManager.QueueExists(queueDesc.Path))
{
namespaceManager.CreateQueue(queueDesc);
}
QueueClient topicClient = QueueClient.CreateFromConnectionString(connectionString, queueDesc.Path);
int sentMsgCount = 0;
int recdMsgCount = 0;
for (int i = 0; i < 100; i++)
{
BrokeredMessage msg = new BrokeredMessage("Test message " + i);
topicClient.Send(msg);
sentMsgCount++;
Console.WriteLine("Sent Message: " + msg);
}
QueueClient subClient = QueueClient.CreateFromConnectionString(connectionString, queueDesc.Path);
bool moreMessages = true;
while (moreMessages)
{
BrokeredMessage recdMsg = subClient.Receive(TimeSpan.FromSeconds(3));
if (recdMsg != null)
{
Console.WriteLine("Received Message: " + recdMsg);
recdMsgCount++;
recdMsg.Complete();
}
else
{
moreMessages = false;
}
}
Console.WriteLine("# of sent msgs: " + sentMsgCount + ", # of rec'd msgs: " + recdMsgCount);
Console.Read();
}
}
这是一个奇怪的问题。通过随机遍历“尝试”,我最终更改了队列的字符串名称,然后一切又开始工作。除了队列名称之外,我没有更改任何内容 - 根本没有更改任何配置参数。
Azure 上的特定队列似乎存在问题。
Azure 服务总线提供持久的消息传递,因此您不会丢失任何消息。一些需要进一步调查的项目: 1) 是否有另一个工作角色实例正在从该队列中提取消息 2)您是否使用 peek-lock 作为接收模式,因为这将是保证至少一次交付的唯一方法。接收和删除模式没有保证 3) 是由于消息过期或超过最大传递计数而进入死信队列的消息,即多次收到但未完成 4) 如果上述情况均不适用,则提出支持票证,Azure 产品团队可以调查症状,因为正如我提到的,这是一个持久的消息系统,因此不会“丢失”任何消息。
我的项目中有 WindowsAzure.ServiceBus NuGet 包,并使用
QueueClient.Send()
发送消息,并面临相同的消息丢失问题。
我彻底解决问题的解决方案:
在发送端,我必须使用 REST API 来发送消息。
在接收端,这就是我提取消息正文的方式:
using (var stream = brokeredMessage.GetBody<Stream>())
{
using (var streamReader = new StreamReader(stream, Encoding.UTF8))
{
var msg = streamReader.ReadToEnd();
// Convert the JSON message to an object
// var obj = JsonConvert.DeserializeObject<ObjectType>(msg);
}
}
我也遇到了同样的问题,发送一条消息效果很好,但在高峰时间有些消息会默默地被丢弃。
我的例子中的问题是队列上设置的默认过期时间太低,因此消息在消费者能够处理它们之前就过期了。默认情况下,这些消息会被丢弃,但可以将队列设置为将它们移动到死信队列,这使得对丢失消息进行故障排除更加容易。