Azure ServiceBus:无法从队列接收消息

时间:2017-01-01 17:36:24

标签: javascript azure azureservicebus

我正在使用此代码接收来自队列的消息:

function startReceiver(){
serviceBusService.getQueue(configurations.queueForRequest, function(err, queue){
    if(!err){
    var length = queue.CountDetails['d2p1:ActiveMessageCount'];//get count of active messages
    if(length > 0) {        
    serviceBusService.receiveQueueMessage(configurations.queueForRequest, {isPeekLock:true},
         function(error, lockedMessage){ HandleMessage(error, lockedMessage) });
    return; //get out from this method
               }
            }
            else{
                console.log('Can not get queue');
            }
        setTimeout(startReceiver, 3000);//if err or there are no messages then call this method later
        });    
    }

function handleMessage(err, msg){           
    var result;
    if (!err){
    serviceBusService.deleteMessage(msg, function(deleteError){
            if(deleteError) {
            console.log('Can not delete the message')
            }
            else{
            console.log('Msg has been deleted');
            }
          });//delete the message which has been received

    try{                
        result = GetResult(msg.body)        
    }
    catch (er){
        result = GetResultWhenExp();
    }
    finally{
        sendMessage(result); //send a response
        startReceiver(); //repeat a receiver loop
    }

    }//!error
    else{console.log('Error occured: '+err);
     setTimeout(startReceiver, 3000); //repeat a receiver loop later
    }
}

问题是当handleMessage()仅在第一次运行时我可以收到消息。进一步的startReceiver()可以获得正确的活动消息计数,但handleMessage()获取未定义的msg作为参数始终(即serviceBusService.receiveQueueMessage()失败,错误是“没有要接收的消息”)。

使用C#库及其标准功能来接收消息,效果很好。

这里有什么问题?请帮忙

编辑:我只是从azure-sdk-for-node存储库中复制粘贴this example,在我的情况下,它会产生相同的行为:第一条消息已成功收到,但是请求后续到总线返回“没有要接收的消息”

3 个答案:

答案 0 :(得分:1)

目前,我可以提出您的问题,并检测到它应该是某种复杂场景中的性能问题,该场景与Peek-Lock模式相关,以便从队列接收消息。

在您的代码段中,您使用deleteMessage()模式接收消息,这将锁定队列的第一条消息(作为队列传递消息FIFO),作为handleMessage()中的startReceiver()函数是一个asyn函数,因此node.js不会等待此结果,会立即调用finally部分中的startReceiver()。在这种情况下,它可能会尝试接收锁定的消息并出现此问题。

您可以尝试两种操作来解决此问题:

  • 放大接收处理器的间隔时间,尝试将finally部分下的setTimeout(startReceiver, 3000);修改为read and delete
  • 尝试使用receiveQueueMessage(quene_name,callback)接收模式,使用receiveQueueMessage(quene_name,{ isPeekLock: true },callback)代替 ac.sumPer=((ac.sum/5)*100); ac.test='p'+ac.sumPer; console.log(ac.test); $('#change').addClass("c100 big dark ac.test");

答案 1 :(得分:0)

最后我找到了解决这个问题的方法。

起初我认为原因是Node.js的Azure包已经过时了。 但事实并非如此。

当我手动创建队列时,即通过azure portal我的node.js客户端工作错误(它无法接收消息)。 当使用代码(createQueueIfNotExists方法)创建它时,没有任何问题。

它为我工作但我对此行为的细节一无所知,我向他们询问了这个团队。

答案 2 :(得分:0)

这是因为,默认情况下,从天蓝色门户网站创建新队列时,会选中“分区”复选框。创建队列之前,请取消选中“分区”复选框。

由于某些原因,当从队列中读取消息时,节点客户端似乎从随机分区中抢夺。您将从空的分区中获得“无消息可接收”错误。我找不到任何说明如何将sdk节点与分区队列一起使用的文档。

编辑:

以下是一些说明分区的文档: https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-partitioning

经过一番挖掘,我发现其余客户端(节点客户端使用的节点)不支持会话,换句话说,当您从队列中读取消息时,您无法告诉客户端要使用哪个分区。