Azure Service Bus订户定期打电话回家?

时间:2013-09-03 17:47:09

标签: c# asp.net azure tcp

我们有pub / sub应用程序,涉及通过Azure Service Bus主题订阅Web角色发布者的外部客户端。我们当前的结算周期表示我们已发送/接收了> 25K消息,而我们的信息中心表示我们已发送< 100。我们正在调查我们的实施并检查我们的假设,以便了解这种差异。

作为调查的一部分,我们在客户端计算机上收集了客户端< =>服务总线流量的wireshark捕获。我们注意到了一种我们尚未见过的常规沟通模式,并且希望更好地理解。如果总线上没有活动,则每50秒进行一次以下交换:

  1. 客户端将~200B推送到服务总线。
  2. 10s后,服务总线将~800B推送到客户端。客户端注册空消息的接收(通过断点确定。)
  3. 客户端立即通过将~1000B推送到服务总线来响应。
  4. 一些相关信息:

    • 当我们的Web角色没有主动将数据推送到服务总线时,会发生这种情况。
    • 收到来自Web角色的合法消息后,上述模式将不会再发生,直到整整50秒过去。
    • 客户端和服务器都通过TCP连接到sb:// 名称空间 .servicebus.windows.net。
    • 我们的应用程序消息是< 64 KB

    问题

    1. 我们看到的常规3分组消息交换负责什么?它是某种保持活力吗?
    2. 将3个数据包中的每一个计为单独的可计费消息吗?
    3. 此行为是否可配置或以其他方式记录?
    4. 编辑:

      这是接收消息的代码:

          private void Listen()
          {
              _subscriptionClient.ReceiveAsync().ContinueWith(MessageReceived);
          }
      
          private void MessageReceived(Task<BrokeredMessage> task)
          {
              if (task.Status != TaskStatus.Faulted && task.Result != null)
              {
                  task.Result.CompleteAsync();
                  // Do some things...
              }
              Listen();
          }
      

1 个答案:

答案 0 :(得分:7)

我认为您所看到的是后台接听电话。在幕后,接收呼叫都使用长轮询。这意味着他们呼叫服务总线端点并要求提供消息。 Service Bus服务获取该请求,如果有消息,它将立即返回。如果它没有消息,它将保持连接打开一段时间以防消息到达。如果消息在该时间范围内到达,则将其返回给客户端。如果在时间帧结束时消息不可用,则会向客户端发送响应,指示没有消息存在(也就是您的null BrokeredMessage)。如果您在没有重载的情况下调用Receive(就像您在此处所做的那样),它将立即发出另一个请求。此循环继续发生,直到收到消息。

因此,您所看到的是客户端请求消息但在那里没有消息的次数。长轮询使其比Windows Azure存储队列更好,因为如果没有消息,它们将立即返回null结果。对于这两种技术,通常会对请求实施指数退避。有很多关于如何做到这一点的例子。这会减少您检查队列的频率,并减少您的交易次数。

回答你的问题:

  1. 是的,这是正常的预期行为。

  2. 不,这只是一个交易。对于Service Bus,每次将消息放入队列并且每次请求消息时都会收取一笔交易(鉴于Recieve在后台多次拨打电话,这可能会有点不透明)。请注意,文档指出您需要为每个空闲事务收费(意味着来自Receive调用的结果为空)。

  3. 同样,您可以实施退避方法,以便您不会经常访问队列。我最近听到的另一个建议是,如果你有一个没有看到大量流量的队列,你也可以检查队列深度,看看它是否是&gt;在进入循环进行处理之前为0,如果从接收呼叫中没有收到任何消息,您可以返回查看队列深度。我没试过,如果你经常进行队列深度检查,你可能会受到限制。

  4. 如果这些是您的生产号码,那么您的订阅并不真正处理大量消息。在处理之前等待可以接受的时间可能是一个非常好的主意。比如,如果一条消息可以存在超过10分钟,那么创建一个退出方法,最终只需每10分钟检查一条消息,然后当它获得一个进程并立即再次检查时。

    哦,有一个接收超载需要超时,但我不是100%,这是服务器超时或本地超时。如果它是本地的,那么它仍然可以每隔X秒向服务进行一次调用。我认为这是基于在创建SubscriptionClient时在Messaging Factory设置上设置的OperationTimeout值。你必须测试它。