尝试使用Node.js编写的WebJob轮询Azure Service Bus队列。我创建了2个WebJobs。第一个是按需,并向队列发送10个唯一消息。第二个作业是连续的,并轮询队列中的消息。
遇到以下问题:
投票很慢。收到10条消息平均需要10分钟左右。请参阅下面的示例日志详情在这个速度下基本上无法使用。所有延迟都来自memcopy
的回复。响应时间从0秒到约120秒不等,平均为60秒。
正在以随机顺序接收消息。不是FIFO。
有时会收到两次消息,即使它们是在ReceiveAndDelete模式下读取的(我尝试过没有读取模式参数,默认为ReceiveAndDelete,receiveQueueMessage
和{isReceiveAndDelete:true}
相同的结果)。
当队列为空时,它应该使接收请求保持打开一天,但它总是在230秒后返回no消息错误。根据文件记录,最长为24天,所以我不知道230秒的来源:
Service Bus中阻塞接收操作的最大超时时间 队列是24天。但是,基于REST的超时具有最大值 55秒。
基本上没有任何广告可行。我做错了什么?
发送消息测试工作:
{isPeekLock:false}
接收消息连续作业:
var uuid = require('node-uuid');
var azure = require('azure');
var serviceBus = azure.createServiceBusService(process.env.busSearchConnectionString);
var messagesToSend = 10;
sendMessage(0);
function sendMessage(count)
{
var message = {
body: 'test message',
customProperties: {
message_number: count,
sent_date: new Date
},
brokerProperties: {
MessageId: uuid.v4() //ensure that service bus doesn't think this is a duplicate message
}
};
serviceBus.sendQueueMessage(process.env.busSearchQueueName, message, function(err) {
if (!err) {
console.log('sent test message number ' + count.toString());
} else {
console.error('error sending message: ' + err);
}
});
//wait 5 seconds to ensure messages are received by service bus in correct order
if (count < messagesToSend) {
setTimeout(function(newCount) {
//send next message
sendMessage(newCount);
}, 5000, count+1);
}
}
示例日志输出:
console.log('listener job started');
var azure = require('azure');
var serviceBus = azure.createServiceBusService(process.env.busSearchConnectionString);
listenForMessages(serviceBus);
function listenForMessages(serviceBus)
{
var start = process.hrtime();
var timeOut = 60*60*24; //long poll for 1 day
serviceBus.receiveQueueMessage(process.env.busSearchQueueName, {timeoutIntervalInS: timeOut, isReceiveAndDelete: true}, function(err, message) {
var end = process.hrtime(start);
console.log('received a response in %ds seconds', end[0]);
if (err) {
console.log('error requesting message: ' + err);
listenForMessages(serviceBus);
} else {
if (message !== null && typeof message === 'object' && 'customProperties' in message && 'message_number' in message.customProperties) {
console.log('received test message number ' + message.customProperties.message_number.toString());
listenForMessages(serviceBus);
} else {
console.log('invalid message received');
listenForMessages(serviceBus);
}
}
});
}
答案 0 :(得分:4)
问题是我正在使用的队列是分区的(在Azure门户中创建队列时的默认选项)。一旦我创建了一个没有分区的新队列,一切都按预期工作,没有延迟(除了长时间轮询尝试的奇怪的230秒超时)。所以node.js库基本上不适用于分区队列。完全没有。浪费了很多天才想出那一个。将此留给其他人。
答案 1 :(得分:1)
关闭Service Bus队列的分区标志也适用于我。
对于分区队列,某些消息的延迟超过30分钟。 一个简单的DotNet webclient可以毫不拖延地下载所有消息。但是,只要nodejs下载消息,只会下载第一条消息而不会出现问题,之后会出现延迟。使用nodejs来更改http代理选项keepalive和套接字超时并没有改善这种情况。
在停止nodejs之后,我不得不等待几分钟才能使DotNet客户端真正开始正常工作。这可以重复几次。我还发现简单的DotNet webclient程序在连续几次启动和停止后显示出类似的问题。
无论如何,你的帖子向我展示了解决方案:关闭分区标志:)
答案 2 :(得分:1)
尝试使用amqp从 azure服务总线分区队列中读取消息,这将适用于分区主题/队列,您甚至不需要轮询很多。< / p>
const AMQPClient = require('amqp10').Client;
const Policy = require('amqp10').Policy;
const protocol = 'amqps';
const keyName = 'RootManageSharedAccessKey';
const sasKey = 'your_key_goes_here';
const serviceBusHost = 'namespace.servicebus.windows.net';
const uri = `${protocol}://${encodeURIComponent(keyName)}:${encodeURIComponent(sasKey)}@${serviceBusHost}`;
const queueName = 'partitionedQueueName';
const client = new AMQPClient(Policy.ServiceBusQueue);
client.connect(uri)
.then(() => Promise.all([client.createReceiver(queueName)]))
.spread((receiver) => {
console.log('--------------------------------------------------------------------------');
receiver.on('errorReceived', (err) => {
// check for errors
console.log(err);
});
receiver.on('message', (message) => {
console.log('Received message');
console.log(message);
console.log('----------------------------------------------------------------------------');
});
})
.error((e) => {
console.warn('connection error: ', e);
});