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

Joh*_*err 4 c# asp.net tcp azure

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

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

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

一些相关信息:

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

问题

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

编辑:

这是接收消息的代码:

    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();
    }
Run Code Online (Sandbox Code Playgroud)

Mik*_*eWo 7

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

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

回答你的问题:

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

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

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

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

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