Eventlet /常规异步I / O任务粒度

时间:2012-05-25 20:26:38

标签: python eventlet granularity

我正在开发一个Web后端/ API提供程序,它从第三方Web API获取实时数据,将其放入MySQL数据库并通过HTTP / JSON API提供。

我正在使用SQLAlchemy Core为API提供烧瓶并使用DB。

对于实时数据获取部分,我有通过发送请求包装第三方API的函数,将返回的xml解析为Python dict并返回它。我们将这些API包装称为。

然后我在其他方法中调用这些函数,这些方法获取相应的数据,在需要时进行任何处理(如时区转换等)并将其放入数据库中。我们称之为处理器。

我一直在阅读异步I / O和eventlet,我印象非常深刻。

我将把它合并到我的数据抓取代码中,但我先问了一些问题:

  1. 我可以安全地修补一切吗?考虑到我有烧瓶,SQLAlchemy和一堆其他的库,猴子补丁是否有任何缺点(假设没有后期绑定)?

  2. 我应该将任务划分为什么粒度?我在考虑创建一个定期生成处理器的池。然后,一旦处理器到达它调用API包装器的部分,API包装器将启动GreenPile以使用eventlet.green.urllib2获取实际的HTTP数据。这是一个好方法吗?

  3. 超时 - 我想确保没有任何希腊语挂起。对于每个greenthread,将eventlet.Timeout设置为10-15秒是一个好方法吗?
  4. 仅供参考,我有大约10组不同的实时数据,每隔约5-10秒就会产生一个处理器。

    谢谢!

2 个答案:

答案 0 :(得分:3)

我认为将Flask / SQLAlchemy与异步样式(或事件驱动)编程模型混合是不明智的。

但是,由于您声明您使用的是RDBMS(MySQL)作为中间存储,为什么不创建异步工作程序来存储RDMBS中第三方Web服务的结果,并保留您的前端(Flask / SQLAlchemy)同步?

在这种情况下,您不需要monkeypatch Flask或SQLAlchemy。

关于粒度,您可能希望使用mapreduce范例来执行Web API调用和处理。这种模式可以让您了解如何在逻辑上分离连续的步骤,以及如何控制所涉及的过程。

就个人而言,我不会使用异步框架来执行此操作。最好使用多处理,Celery或真正的mapreduce类型的系统,如Hadoop

只是一个提示:从小做起,保持简单和模块化,并在以后优化,如果您需要更好的性能。这可能也会受到您希望信息实时性的影响。

答案 1 :(得分:-1)

修补纯python和使用标准库写的模块是安全的。

  • 几乎没有纯mysql适配器:
  • PyMysql有一个sqlalchemy测试套件,您可以为您的案例运行测试。
  • 有一个名为pymysql_sa的模块为sqlalchemy提供方言
  • Flask由纯python和100%WSGI 1.0兼容编写。使用 eventlet.wsgi 来提供服务。

尽可能使用绿色模块通过单次抓取来划分任务。将作业放入队列(也由eventlet提供),每个任务工作者从队列中获取作业,然后在完成提取后将结果保存到db中,或发送到event.Event对象以触发等待的作业任务完成。或者,这两个过程。

更新:

eventlet官方文档强烈建议在主模块的第一行使用补丁,并且可以安全地多次调用monkey_patch。更多信息请参阅第http://eventlet.net/doc/patching.html

有些绿色模块可以使用eventlet,所有这些都在eventlet.green中。 bitbucket上的列表。 确保在代码中使用绿色模块,或者在导入使用标准库的第3个模块之前对其进行修补。

但是monkey_patch只接受少量模块,需要手动导入绿色模块。

def monkey_patch(**on):
    """Globally patches certain system modules to be greenthread-friendly.

    The keyword arguments afford some control over which modules are patched.
    If no keyword arguments are supplied, all possible modules are patched.
    If keywords are set to True, only the specified modules are patched.  E.g.,
    ``monkey_patch(socket=True, select=True)`` patches only the select and 
    socket modules.  Most arguments patch the single module of the same name 
    (os, time, select).  The exceptions are socket, which also patches the ssl 
    module if present; and thread, which patches thread, threading, and Queue.

    It's safe to call monkey_patch multiple times.
    """    
    accepted_args = set(('os', 'select', 'socket', 
                         'thread', 'time', 'psycopg', 'MySQLdb'))
    default_on = on.pop("all",None)