Python Eventlet/通用异步I/O任务粒度

Python Eventlet/通用异步I/O任务粒度,python,eventlet,granularity,Python,Eventlet,Granularity,我正在开发一个web后端/API提供程序,它从第三方web API获取实时数据,将其放入MySQL数据库中,并通过HTTP/JSON API使其可用 我使用flask提供API,并使用SQLAlchemy Core处理DB 对于实时数据获取部分,我有一些函数,它们通过发送请求、将返回的xml解析为Python dict并返回来包装第三方API。我们将调用这些API包装器 然后,我在其他方法中调用这些函数,这些方法获取各自的数据,如果需要,执行任何处理(如时区转换等),并将其放入数据库中。我们称这

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

我使用flask提供API,并使用SQLAlchemy Core处理DB

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

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

我一直在阅读有关异步I/O和eventlet的专门书籍,印象非常深刻

我将把它合并到我的数据采集代码中,但首先我有一些问题:

  • 我用猴子修补所有东西安全吗?考虑到我有flask、SQLAlchemy和一堆其他LIB,monkey补丁有什么缺点吗(假设没有后期绑定)

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

  • 超时-我想确保没有绿色线程挂起。将每个绿色线程的eventlet.Timeout设置为10-15秒是一种好方法吗
  • 仅供参考,我有大约10组不同的实时数据,每5-10秒产生一个处理器


    谢谢

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

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

    在这种情况下,您不需要使用monkeypatch烧瓶或SQLAlchemy

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

    就我个人而言,我不会使用异步框架来实现这一点。最好使用多处理或真正的mapreduce之类的系统


    只是一个提示:从小处开始,保持简单和模块化,如果您需要更好的性能,请稍后进行优化。这也可能受到您希望信息的实时性的严重影响。

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

    • 纯mysql适配器很少:
      • ,
    • PyMysql有一个sqlalchemy测试套件,您可以为您的案例运行测试
    • 有一个名为pymysql_sa的模块为sqlalchemy提供方言
    • Flask由纯python编写,100%符合WSGI 1.0。使用eventlet.wsgi提供服务
    尽可能使用绿色模块将任务划分为单个提取。将作业放入队列(也是由eventlet提供的),每个任务工作者从队列中获取作业,然后在完成获取后将结果保存到db中,或者发送到event.event对象以触发等待任务完成的作业。或者,这两个进程都是如此

    更新:

    eventlet官方文档强烈建议在主模块的第一行使用补丁,多次调用monkey_补丁是安全的。请阅读第页的更多信息

    有一些绿色模块可以使用eventlet,它们都在eventlet.green中。名单。 确保在代码中使用绿色模块,或者在导入使用标准libs的第三个模块之前对其进行修补

    但是monkey_补丁只接受很少的模块,需要手动导入绿色模块

    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) def monkey_补丁(**打开): “”“全局将某些系统模块修补为绿色线程友好型。 关键字参数提供了对修补哪些模块的一些控制。 如果未提供任何关键字参数,则所有可能的模块都将进行修补。 如果关键字设置为True,则仅修补指定的模块。例如。, ``monkey_补丁(socket=True,select=True)``只补丁select和 套接字模块。大多数参数修补同名的单个模块 (操作系统,时间,选择)。例外情况是套接字,它也会修补ssl 模块(如果存在);以及线程,用于修补线程、线程和队列。 多次调用monkey_补丁是安全的。 """ accepted_args=set(('os','select','socket',', ‘线程’、‘时间’、‘psycopg’、‘MySQLdb’)
    default_on=on.pop(“全部”,无)谢谢您的评论。我同意不混合Flask和异步I/O,我的问题一定不清楚,但API(Flask)运行在单独的、未修补的非异步I/O进程上。数据采集程序运行在一个经过修补的进程上,使用SQLAlchemy Core(而不是ORM)写入数据库只是为了简化。好的,在这种情况下,您已经这样做了。我想知道你是否真的需要异步的数据采集。您可能会更好地使用其他并发方法(多处理、芹菜等),尤其是如果您的数据采集程序是CPU密集型的。