Azure Service Bus - 针对python客户端

时间:2018-01-10 05:09:44

标签: python azure azureservicebus azure-servicebus-queues azure-servicebus-topics

我正在查看服务AutoRenewTimeout功能的文档,并在Lock Renewal Policy on service-bus messages上发现了这篇文章。

它讨论了 AutoRenewTimeout 功能,其中邮件被锁定了一段时间,以便订阅者可以完成对邮件的处理或邮件超时(无法处理给定的邮件)从同一订阅中读取其他订阅者的消息。

我无法在Microsoft Azure SDK for Python中找到此功能。 我已经浏览了源代码,它只讨论了特定消息的Manual renewal of the lock

我的用例如下

  • 我必须阅读并处理来自servicebus的消息。
  • 将这些处理过的消息转发到数据库中(在我的情况下是MongoDB)
  • 推送到servicebus的消息可能高达每小时100万个事件(因此无法跟踪给定消息何时发生 超时和消防手册更新相同)。
  • 所有处理过的消息都被推送到临时列表中。
  • 每当上面的列表超出特定阈值时,请在DB上执行批量插入

这是我想出的。它没有我正在讨论的锁更新政策。我只是在处理邮件时触发删除。

class Event:
    def __read_subscription_message(self):
        try:
            message = self.bus_service.receive_subscription_message(
                self.topic_name, self.subscription_name, peek_lock=True)
            return message
        except Exception as e:
            self.logger.exception("Exception occurred!!!")

    def start_listner(self, task_number=0):
        self.logger.info('Task: %s, started listening to service bus messages' % task_number)
        while True:
            msg = self.__read_subscription_message()
            if msg and msg.body is not None:
                self.currentBackOff = 0
                self.process_event(msg, task_number)
                gevent.sleep(0)

    def process_event(self, msg, task_number=0):
        try:
            if msg.body:
                # message = json.loads(msg.body.decode())
                message = self.deserialize_message_body(msg.body)
                custom_properties = msg.custom_properties
                # Business logic implemented................
                # After processing a message append this to a temp list. Make
                # an insert which length of this list reaches a given threshold
                # by calling "write_to_storage(self, task_number=0)"
                self.bulk_records.append(record)
                msg.delete()
            else:
                self.logger.info("Message received: %s, is of type: %s" % (msg.body, type(msg.body)))
            self.total += 1
        except DeSerializationException as e:
            self.logger.info("Not able to de-serialize message: %s" % msg.body)
            self.logger.exception(e)
        except Exception as e:
            self.logger.exception(e)

    def write_to_storage(self, task_number=0):
        # Write to DB

它工作正常,但是如果我的订阅者进程被杀死,那么我临时存储桶中的所有消息(未写入数据库)都会丢失。我希望在将消息写入数据库时​​触发手册“message.delete()”。我认为AutoRenewLock是要走的路,因为消息的锁定持续时间的最大值是5分钟,这对我的情况没有帮助。

谢谢

1 个答案:

答案 0 :(得分:0)

因此您不需要在临时日志中编写消息。如果你使用peek lock并且锁定到期,那么消息应该返回到队列中并在下一次被拾取。如果你使用peek lock,你需要调用你在代码中执行的message.delete(),然后才能从代理中删除它。 这个.net示例展示了它应该如何工作: https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-get-started-with-queues

为方便起见: //完成消息,以便不再接收消息。 //只有在ReceiveMode.PeekLock模式下创建queueClient时才能这样做(默认情况下)。

await queueClient.CompleteAsync(message.SystemProperties.LockToken);

此处还可以看到peek lock应该如何工作:https://docs.microsoft.com/en-us/rest/api/servicebus/peek-lock-message-non-destructive-read

因此,除非您调用msg.delete,否则消息不应计为已完成。您是否在同一订阅或主题上运行多个订阅者?

无论您何时不拨打电话,消息都应该返回队列,您的下一个接听电话将会接听。如果你多次没有收到,他们可能会死信。 https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dead-letter-queues

请使用服务总线资源管理器查看您是否真的丢失了消息,或者他们是刚回到队列中还是死信: https://github.com/paolosalvatori/ServiceBusExplorer/releases