Eventlet/общая асинхронная задачация ввода-вывода

Я работаю над веб-сервером/поставщиком API, который захватывает данные в реальном времени от стороннего веб-API, помещает его в базу данных MySQL и делает его доступным через API HTTP/JSON.

Я предоставляю API флягой и работаю с БД с помощью ядра SQLAlchemy.

Для части захвата данных в реальном времени у меня есть функции, которые обертывают сторонний API, отправляя запрос, разыгрывая возвращенный xml в питоне Python и возвращая его. Мы будем называть эти обертки API.

Затем я вызываю эти функции в рамках других методов, которые принимают соответствующие данные, обрабатывают, если необходимо, (например, преобразования часовых поясов и т.д.) и помещают их в БД. Мы будем называть эти процессоры.

Я читал об асинхронных вводах и событиях, и я очень впечатлен.

Я собираюсь включить его в свой код захвата данных, но сначала у меня есть некоторые вопросы:

  • Безопасно ли мне обезглавить все? учитывая, что у меня есть фляга, SQLAlchemy и множество других libs, есть ли какие-либо недостатки для исправления обезьян (если нет позднего связывания)?

  • Какую степень детализации я должен разделить на свои задачи? Я подумывал создать пул, периодически создающий процессоры. Затем, как только процессор достигнет той части, где он вызывает обертки API, обертки API запустит GreenPile для получения фактических данных HTTP с помощью eventlet.green.urllib2. Это хороший подход?

  • Тайм-ауты - я хочу убедиться, что greenthreads никогда не зависает. Это хороший подход для установки eventlet.Timeout до 10-15 секунд для каждого greenthread?

FYI, у меня около 10 различных наборов данных в реальном времени, и процессор генерируется каждые ~ 5-10 секунд.

Спасибо!

Ответ 1

Я не думаю, что было бы разумно смешивать Flask/SQLAlchemy с моделью программирования с асинхронным стилем (или событием).

Однако, поскольку вы заявляете, что используете RDBMS (MySQL) в качестве промежуточного хранилища, почему бы вам просто не создать асинхронных рабочих, которые хранят результаты из ваших сторонних веб-сервисов в RDMBS и сохранять свой интерфейс (Flask/SQLAlchemy) синхронно?

В этом случае вам не нужно monkeypatch Flask или SQLAlchemy.

Что касается детализации, вы можете использовать парадокс mapreduce для выполнения вызовов и обработки веб-API. Этот шаблон может дать вам некоторое представление о том, как логически разделять последовательные шаги и как управлять задействованными процессами.

Лично я не использовал бы асинхронную структуру для этого. Лучше использовать либо многопроцессорную обработку, Celery, либо реальную систему mapreduce, такую ​​как Hadoop.

Просто подсказка: начинайте с малого, держите его простым и модульным и оптимизируйте позже, если вам требуется более высокая производительность. На это также может в большой степени повлиять то, как в реальном времени вы хотите, чтобы информация была.

Ответ 2

Безопасно исправлять модуль, написанный чистым питоном и используя стандартную библиотеку.

  • существует несколько чистых адаптеров mysql:
  • PyMysql имеет набор тестов sqlalchemy, вы можете запустить тест для своих случаев.
  • Существует модуль с именем pymysql_sa для предоставления диалектов для sqlalchemy
  • Флажок написан чистым питоном и 100% WSGI 1.0. используйте eventlet.wsgi для предоставления услуги.

Разделите задачи на одиночную выборку, используя зеленый модуль, как можете. Поместите задания в очередь, которые также предоставлены eventlet, каждый работник задачи получает задание из очереди, затем сохраняет результат в db после завершения выборки или отправляет объект event.Event для запуска задания, которое ожидает task finish.Or, оба этих процесса.

ОБНОВЛЕНО:

В официальном документе на 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 safe to call monkey_patch multiple times.
    """    
    accepted_args = set(('os', 'select', 'socket', 
                         'thread', 'time', 'psycopg', 'MySQLdb'))
    default_on = on.pop("all",None)