2012-05-25 8 views
10

Estoy trabajando en un proveedor backend/API web que toma datos en tiempo real de una API web de terceros, los coloca en una base de datos MySQL y los pone a disposición en una API HTTP/JSON.Eventlet/async general Granularidad de la tarea de E/S

Proporciono la API con matraz y trabajo con la base de datos con SQLAlchemy Core.

Para la parte de captura de datos en tiempo real, tengo funciones que envuelven la API de terceros enviando una solicitud, analizando el xml devuelto en un dict de Python y devolviéndolo. Llamaremos a estos envoltorios API.

Llamo a estas funciones dentro de otros métodos que toman los datos respectivos, realizan cualquier procesamiento si es necesario (como conversiones de zona horaria, etc.) y lo colocan en la base de datos. Llamaremos a estos procesadores.

He estado leyendo sobre E/S asincrónica y eventlet específicamente y estoy muy impresionado.

voy a incorporarlo en mis datos acaparamiento de código, pero tengo algunas preguntas primero:

  1. es seguro para mí parche mono todo? teniendo en cuenta que tengo matraz, SQLAlchemy y un montón de otras librerías, ¿hay alguna desventaja en el parche de monos (suponiendo que no haya un enlace tardío)?

  2. ¿Cuál es la granularidad en la que debería dividir mis tareas? Estaba pensando en crear un grupo que genere periódicamente procesadores. Luego, una vez que el procesador llega a la parte donde llama a los contenedores de API, los contenedores de API iniciarán un GreenPile para obtener los datos HTTP reales utilizando eventlet.green.urllib2. ¿Es este un buen enfoque?

  3. Tiempos de espera - Quiero asegurarme de que no cuelgue nunca el hilo verde. ¿Es un buen enfoque para establecer el evento. Tiempo de espera a 10-15 segundos por cada hilo verde?

FYI, tengo aproximadamente 10 conjuntos diferentes de datos en tiempo real, y se genera un procesador cada ~ 5-10 segundos.

Gracias!

Respuesta

3

No creo que sea sensato mezclar Flask/SQLAlchemy con un modelo de programación de estilo asincrónico (o controlado por eventos).

Sin embargo, como dice que está utilizando un RDBMS (MySQL) como almacenamiento intermediario, ¿por qué no crea simplemente trabajadores asincrónicos que almacenan los resultados de los servicios web de terceros en el RDMBS y mantiene su interfaz (Frasco/SQLAlchemy) sincrónico?

En ese caso, no necesita usar monkeypatch Flask o SQLAlchemy.

En cuanto a la granularidad, es posible que desee utilizar el paradigma mapreduce para realizar las llamadas y el procesamiento de la API web. Este patrón puede darle una idea de cómo separar de forma lógica los pasos consecutivos y cómo controlar los procesos involucrados.

Personalmente, no utilizaría un marco asíncrono para hacer esto. Puede ser mejor usar multiprocesamiento, Celery, o un tipo de sistema de mapreduce real como Hadoop.

Solo una pista: comience poco a poco, manténgalo simple y modular y optimice más adelante si necesita un mejor rendimiento. Esto también puede estar muy influenciado por la forma en que usted quiere que la información en tiempo real.

+0

gracias por su comentario. Acepto no mezclar Flask y Async I/O; no debe haber quedado claro a partir de mi pregunta, pero API (Flask) se ejecuta en un proceso de E/S no asincrónico no parcheado. El capturador de datos se ejecuta en un proceso parcheado, escribiendo en el DB utilizando SQLAlchemy Core (no ORM) solo para fines de simplificación. – user1094786

+0

OK, en ese caso ya lo estás haciendo de esta manera. Sin embargo, me pregunto si realmente necesitas una sincronización para el capturador de datos. Puede ser mejor con otros métodos de concurrencia (multiprocesamiento, apio, etc.), especialmente si su capturador de datos consume mucha CPU. –

+0

+1 para apio. La tarea parece ser un buen candidato para ella. – Tisho

-1

Es seguro parchar un módulo escrito por pure python y usando lib estándar.

  • hay unos adaptadores de MySQL puros:
  • PyMysql tiene un conjunto de pruebas sqlalchemy, podría ejecutar la prueba para sus casos.
  • Hay un módulo llamado pymysql_sa para proporcionar dialecto para sqlalchemy
  • Flask está escrito por pure python y 100% compatible con WSGI 1.0. use eventlet.wsgi para proporcionar el servicio.

Divida las tareas por extracción simple usando el módulo verde como sea posible. Coloque los trabajos en una cola, que también proporciona eventlet, cada trabajador de tareas obtiene un trabajo de la cola, luego guarda el resultado en db después de finalizar la búsqueda o envía a un objeto event.Event para desencadenar el trabajo que espera el finalización de la tarea. O ambos, los dos procesos.

Actualizado:

El documento oficial eventlet recomiendan encarecidamente utilizar el parche en la línea de puño del módulo principal, y es seguro llamar monkey_patch varias veces. Obtenga más información en la página http://eventlet.net/doc/patching.html

Hay algún módulo verde que puede funcionar con eventlet, todos ellos están en el eventlet.green. Una lista en bitbucket. Asegúrese de utilizar el módulo verde en su código o parchearlos antes de importar los 3tos módulos que usan las librerías estándar.

Pero monkey_patch solo acepta pocos módulos, es necesario importar el módulo verde manualmente.

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)
Cuestiones relacionadas