我有一个使用python firebase_admin SDK的Tornado应用程序。 当我在单个进程中运行时:
console_server = tornado.httpserver.HTTPServer(ConsoleApplication())
console_server.listen(options.console_port, options.bind_addr)
tornado.ioloop.IOLoop.instance().start()
firebase_admin工作正常。但是当我将其更改为在多进程中运行时:
console_server = tornado.httpserver.HTTPServer(ConsoleApplication())
console_server.bind(options.console_port, options.bind_addr)
console_server.start(4)
tornado.ioloop.IOLoop.instance().start()
这里的最后一行卡住了:
if (not len(firebase_admin._apps)):
cred = ...
self.app = firebase_admin.initialize_app(cred)
self.app = firebase_admin.get_app()
self.db = firestore.client()
...
ref = self.db.document(USER_DOC.format(org, value))
user_ref = ref.get()
似乎get((没有得到解决,因为我没有得到任何异常。
有没有人知道为什么会发生这种情况,或者至少我该如何调试它?
多进程分叉(即start(4)
调用(必须在应用程序生命周期的早期出现。特别是,大多数接触网络的东西都必须在分叉之后(bind()
是少数例外之一,在这种情况下必须在分叉之前(。
您(可能(需要重新组织内容,以便在分叉后创建Firebase应用。如果您使用的是HTTPServer.start
方法,这可能会很烦人,因此您可能希望切换到直接调用tornado.process.fork_processes()
(这被记录为"高级多进程"模式(。
我知道这是一个老问题,但我想分享我关于这个问题的经验,以帮助未来的访问者。
我最近开发了一个使用Firebase Admin Python SDK的multiprocessing
脚本,在我的本地Windows机器中一切正常,但是当我将其部署到Linux服务器中用于生产时,我注意到该脚本卡在get()
函数中。
经过几个小时的搜索,我发现python进程的默认启动方法在Windows和Unix环境中是不同的:Windows使用spawn
作为默认启动方法,而Unix使用fork
。您可以在文档中了解有关启动方法的更多信息。
因此,为了使它在我的 Linux 服务器中工作,我只是将启动方法更改为spawn
:
if __name__ == '__main__':
multiprocessing.set_start_method('spawn') # <-- Set spawn as start_method
# The rest of your script here
# ...