Google .Net 客户端的 Pub Sub 消息拉取延迟问题

Google Pub Sub Message Pull latency Issue with .Net Client

我不断从 Google PubSub 中提取消息。一切顺利,除了获取消息所花费的时间大约为 12 到 15 秒,这在我们的案例中是不可接受的。以下是我的 CallTiming 设置:

 public CallSettings GetPullSetting()
    {
        CallTiming timing = CallTiming.FromRetry(new RetrySettings(
                retryBackoff: new BackoffSettings(new TimeSpan(0, 0, 0, 0, 50), new TimeSpan(0, 0, 5), 1),
                timeoutBackoff: new BackoffSettings(new TimeSpan(0, 0, 0, 18, 0), new TimeSpan(0, 0, 20), 1),
                totalExpiration: Google.Api.Gax.Expiration.FromTimeout(TimeSpan.FromMilliseconds(600000))));

        return CallSettings.FromCallTiming(timing);
    }

我尝试了各种组合以将此延迟减少到最多 3 秒。

一个观察结果是,无论何时成功拉取消息,并且在 pull 的下一次迭代中,如果 pubsub 上有消息,它会立即获取该消息。这意味着如果在连续 pull 中发现消息,延迟非常低。

但问题是,假设在一次迭代中我得到 Deadline exceeded 异常,因为 pubsub 没有消息。然后我在 pubsub 中为下一次迭代推送一条消息。此时需要花费很多时间(13 到 16 秒)。所以重现这个问题的条件是我将有一次失败的尝试来拉取消息。

代码粘贴在这里:

public void PullTest()
        {
            var cont = true;
            SubscriberSettings settings = new SubscriberSettings()
            {
                PullSettings = GetPullSetting()
            };
            SubscriberClient subscriberClient = SubscriberClient.Create(settings: settings);
            var subscriberName = new SubscriptionName("project-name", "subscription-name");
            while (cont)
            {
                try
                {
                    PullResponse response = subscriberClient.Pull(subscriberName, returnImmediately: false, maxMessages: 1);
                    System.Diagnostics.Trace.WriteLine(">>>>>> " + DateTime.Now.ToString());
                    System.Diagnostics.Trace.WriteLine(">>>>>> " + "Job Recieved" + response.ReceivedMessages.ToList().FirstOrDefault());
                    subscriberClient.Acknowledge(subscriberName, new List<string>() { response.ReceivedMessages.ToList().FirstOrDefault().AckId });
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Trace.WriteLine(">>>>>> " + DateTime.Now.ToString());
                    System.Diagnostics.Trace.WriteLine(">>>>>> " + ex.Message);
                }
            }
        }

 public CallSettings GetPullSetting()
        {
            CallTiming timing = CallTiming.FromRetry(new RetrySettings(
                    retryBackoff: new BackoffSettings(new TimeSpan(0, 0, 0, 0, 50), new TimeSpan(0, 0, 5), 1),
                    timeoutBackoff: new BackoffSettings(new TimeSpan(0, 0, 0, 18, 0), new TimeSpan(0, 0, 20), 1),
                    totalExpiration: Google.Api.Gax.Expiration.FromTimeout(TimeSpan.FromMilliseconds(600000))));

            return CallSettings.FromCallTiming(timing);
        }

为了最大限度地减少延迟,您将希望同时处理多个拉取请求。根据您的吞吐量要求,可能需要同时处理数十个未完成的请求。如果您的吞吐量很低,您仍然希望一次有多个拉取请求(至少两个或三个)。一旦他们中的任何一个 returns,无论是超过截止日期还是收到消息,都会启动另一个拉取请求。目标是始终有未完成的拉取请求等待接收已发布的消息。

当超时期限超过时,您在连续拉取之间出现退避问题。您本质上是在寻找一种长轮询解决方案,为此您需要将退避时间减少到接近 0,或者使用自定义 connection/client 立即重试。