我的Python Web应用程序有几个连接注册到同一个MongoDb服务器,但有3个不同的数据库。该申请由4名Gunicorn工作人员负责。
我正在使用副本集。
当主服务器关闭时,当前查询失败并在MongoReplicaSetClient中调度刷新(2.8,但我猜在3.2中它是相同的)。如果时间选择了新的主节点,并且MonitorThread获取有关更新客户端连接的信息,则下一个查询可能会成功。
但刷新仅影响此客户端。连接同一MongoDB服务器的其他客户端不会受到影响 - 每个客户端都会发生相同的故事。 这意味着如果每个工作者连接到同一MongoDB服务器上的3个数据库,并且我重复相同的HTTP请求,当主要服务器失败时使用所有3个数据库,则无限时间更新所有连接的客户端。如果每个HTTP请求循环到4个中的每个工作者,我们需要12个请求来更新每个Mongo客户端。但实际上这些要求并没有循环使用。
查看PyMongo代码
MongoReplicaSetClient._send_message_with_response
我看到,当主要版本关闭时,会调用self.disconnect
来调用self.__schedule_refresh
。此方法具有参数sync
,允许“阻止直到刷新完成”。
我的想法是捕获AutoReconnect
异常并在连接到失败的主要和阻止的所有客户端上调用__schedule_refresh(sync=True)
,直到新的副本集配置到位。因此,在数据库正常之前,不会处理HTTP请求(导致500)。
但是__schedule_refresh
是一种私有方法。此外,我不知道在所有客户端上按顺序调用它会是快速的 - 看起来MonitorThread
会间隔工作。
或许我可以使用MongoReplicaSetClient.refresh
。
您如何看待这个想法?它有缺点吗?
你能帮我实施吗?
答案 0 :(得分:0)
有趣的问题。
如果您在一个有大量请求进入的环境中运行,我建议反对在IO上有任何工作人员阻止,特别是像等待的网络调用为小学生提出来。
我建议尝试从您的mongo客户端捕获可能表明服务器已关闭并向调用者返回503s的异常。 503s通常是传达资源不可用的好方法,并建议稍后重试。
你的mongo数据库 会在使用过程中关闭并让appserver检测到这一点,转储请求并返回503s是一种处理流量的方法,否则会开始阻塞,线程耗尽并杀死应用服务器。让appserver摆脱所有这些会导致等待和可能失败的调用。
这是REST服务中常用的习惯用法:http://www.restpatterns.org/HTTP_Status_Codes/503_-_Service_Unavailable
您甚至可以添加“Retry-After”标头,以指示客户端将来何时尝试重试。有关Retry-After标题的更多信息以及某些浏览器如何解释它:
Retry-after HTTP response header - does it affect anything?
HTH