python - Google PubSub python 客户端返回 StatusCode.UNAVAILABLE

标签 python google-cloud-pubsub

我正在尝试建立对 Google Cloud PubSub 主题的长期运行的 Pull 订阅。 我使用的代码与文档 here 中给出的示例非常相似,即:

def receive_messages(project, subscription_name):
    """Receives messages from a pull subscription."""
    subscriber = pubsub_v1.SubscriberClient()
    subscription_path = subscriber.subscription_path(
        project, subscription_name)

    def callback(message):
        print('Received message: {}'.format(message))
        message.ack()

    subscriber.subscribe(subscription_path, callback=callback)

    # The subscriber is non-blocking, so we must keep the main thread from
    # exiting to allow it to process messages in the background.
    print('Listening for messages on {}'.format(subscription_path))
    while True:
        time.sleep(60)

问题是我有时会收到以下回溯:

Exception in thread Consumer helper: consume bidirectional stream:
Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.5/threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "/path/to/google/cloud/pubsub_v1/subscriber/_consumer.py", line 248, in _blocking_consume
    self._policy.on_exception(exc)
  File "/path/to/google/cloud/pubsub_v1/subscriber/policy/thread.py", line 135, in on_exception
    raise exception
  File "/path/to/google/cloud/pubsub_v1/subscriber/_consumer.py", line 234, in _blocking_consume
    for response in response_generator:
  File "/path/to/grpc/_channel.py", line 348, in __next__
    return self._next()
  File "/path/to/grpc/_channel.py", line 342, in _next
    raise self
grpc._channel._Rendezvous: <_Rendezvous of RPC that terminated with (StatusCode.UNAVAILABLE, The service was unable to fulfill your request. Please try again. [code=8a75])>

我看到这在 another question 中被引用了但在这里我问的是如何在 Python 中正确处理它。我试图将请求包装在异常中,但它似乎在后台运行,如果出现该错误,我将无法重试。

最佳答案

一种对我有用的有点老套的方法是自定义 policy_class .默认的有一个 on_exception 函数忽略 DEADLINE_EXCEEDED。您可以创建一个继承默认值并忽略 UNAVAILABLE 的类。我的看起来像这样:

from google.cloud import pubsub
from google.cloud.pubsub_v1.subscriber.policy import thread
import grpc

class AvailablePolicy(thread.Policy):
    def on_exception(self, exception):
        """The parent ignores DEADLINE_EXCEEDED. Let's also ignore UNAVAILABLE.

        I'm not sure what triggers that error, but if you ignore it, your
        subscriber seems to work just fine. It's probably an intermittent
        thing and it reconnects later if you just give it a chance.
        """
        # If this is UNAVAILABLE, then we want to retry.
        # That entails just returning None.
        unavailable = grpc.StatusCode.UNAVAILABLE
        if getattr(exception, 'code', lambda: None)() == unavailable:
            return
        # For anything else, fallback on super.
        super(AvailablePolicy, self).on_exception(exception)

subscriber = pubsub.SubscriberClient(policy_class=AvailablePolicy)
# Continue to set up as normal.

它看起来很像 original on_exception 只是忽略了一个不同的错误。如果需要,您可以在抛出异常时添加一些日志记录,并验证一切是否仍然有效。以后的消息仍会通过。

关于python - Google PubSub python 客户端返回 StatusCode.UNAVAILABLE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46788681/

相关文章:

python multiprocessing.Array : huge temporary memory overhead

google-cloud-platform - 如何在Dataflow Pipeline完成时触发事件?

.net - PubSub 上的 Http 400 推送到云运行

google-cloud-platform - 云pubsub轮询速度慢

curl - GCP 发布订阅 : Publish message via CURL type of request

google-cloud-pubsub - 创建从 Google Pub/Sub 读取的 Apache Beam 管道

python - 按字符大小分割,但在 Python 正则表达式中完全包含单词

python - 将 Mezzanine 集成到现有 Django 项目中

python - 从youtube视频中提取音频

javascript - 如何用自定义变量替换 DJANGO 中 JAVASCRIPT 脚本生成的 Google map key