如何使用Tornado和APScheduler?

6

我正在运行python的apscheduler,并定期希望执行一些POST操作以访问一些HTTP资源。这将涉及使用tornado的AsyncHttpClient作为计划任务。每个作业将执行多个POST请求。当每个http请求响应时,会调用一个回调函数(我认为Tornado使用future来实现这一点)。

在这里,我担心线程安全问题,因为Apscheduler在各种线程中运行作业。我无法找到有关如何在此上下文中跨多个线程最好使用tornado的充分解释。

在这种情况下,我该如何最好地使用apschedulertornado

具体的问题:

  1. 应该使用哪个tornado ioloop?文档说AsyncHTTPClient "像魔术一样工作"。嗯,魔术让我感到害怕。我需要从当前线程中使用AsyncHTTPClient吗,还是可以使用主线程的(可以指定)?

  2. 我的回调函数是否存在与我使用的ioloop相关的线程安全问题?

  3. 当一个线程完成但仍有待处理的回调/future需要被调用时,不清楚会发生什么。这里存在问题吗?

  4. 由于apscheduler作为进程中的线程运行,并且Python有GIL,那么使用主线程的一个IOLoop几乎与使用来自不同线程的多个循环相同(就性能而言)吗?


嘿,我的回答有帮助到您吗?如果您需要更多相同信息,请在评论中指出。 - vaidik
1个回答

3
  1. Tornado的所有实用工具都围绕着Tornado的IOLoop运作,包括AsyncHTTPClient。而且,IOLoop不被认为是线程安全的。因此,除了运行主IOLoop的线程之外,从任何其他线程运行AsyncHTTPClient都不是一个好主意。关于如何使用IOLoop的更多细节,请参阅这里

  2. 如果您使用tornado.ioloop.IOLoop.instance(),那么我想如果您的意图不是将回调添加到主线程的IOLoop中,那么您可以使用tornado.ioloop.IOLoop.current()来正确地引用正确的IOLoop实例以供正确的线程使用。您将不得不做太多的记录才能将回调添加到另一个非主线程的IOLoop中 - 这将变得非常混乱。

  3. 我不太明白这个。但是我理解有两种情况。要么您正在谈论一个带有IOLoop的线程,要么没有IOLoop。如果线程没有运行IOLoop,则在线程完成后,无论什么回调必须由其他线程(可能是主线程)中的IOLoop执行,都将被执行。另一种情况是,您所谈论的线程具有正在运行的IOLoop。然后,除非您停止IOLoop,否则该线程将不会完成。因此,回调的执行实际上取决于何时停止IOLoop。

  4. 老实说,我不太看得出在Tornado中使用线程的意义。除非您正在运行PyPy,否则不会有任何性能提升,而我不确定Tornado是否与其兼容(并非所有事情都已知可以在其上正常工作,老实说我也不了解Tornado)。如果您的应用程序是Web服务器,则可以拥有多个进程,并使用Nginx作为代理和负载平衡器。由于您引入了apscheduler,我建议使用IOLoop的add_timeout,它几乎可以完成您需要的相同操作,并且它是Tornado本地支持的,更加友好。无论如何,回调都很难调试。与Python的线程结合使用,可能会导致混乱。如果您准备考虑另一个选项,请将所有异步处理移出此进程 - 这将使生活变得轻松得多。考虑使用类似Celery的东西。


1
感谢提供更多信息。我已经开始使用gevent中的greenlets,并且使用最新版本的APScheduler提供了gevent兼容性。同时也将负载分散到多个tornado进程中。 - Rocketman
将负载分散到多个进程比使用Tornado的线程更容易。从管理角度来看,这也是一个更明智的选择。如果我的答案回答了您先前的需求/问题,请您接受它作为答案,谢谢。 - vaidik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接