2012-05-25 17 views
10

Pracuję nad dostawcą interfejsu WWW/API, który pobiera dane w czasie rzeczywistym z interfejsu API innej firmy, umieszcza je w bazie danych MySQL i udostępnia za pośrednictwem interfejsu API HTTP/JSON.Zdarzenie/ogólna asynchronizacja zadań we/wy

Dostarczam API z kolbą i współpracuję z DB przy użyciu SQLAlchemy Core.

Dla części pobierającej dane w czasie rzeczywistym, mam funkcje, które owijają API strony trzeciej, wysyłając żądanie, parsując zwrócone xml do dyktatora Pythona i zwracając go. Nazwiemy te owijki API.

Następnie wywołuję te funkcje w ramach innych metod, które pobierają odpowiednie dane, w razie potrzeby przetwarzam je (np. Konwersje strefy czasowej itp.) I umieszczam je w bazie danych. Nazwiemy te procesory.

Właśnie czytałem o asynchronicznych I/O i wydarzeniu specjalnie i jestem pod wrażeniem.

zamierzam włączyć go w moich danych kod chwytanie, ale mam kilka pytań pierwsze:

  1. jest to bezpieczne dla mnie małpa plastra wszystkiego? biorąc pod uwagę, że mam flakon, SQLAlchemy i kilka innych bibliotek, czy są jakieś minusy łatania małp (zakładając, że nie ma późnego wiązania)?

  2. Jaka jest szczegółowość, na którą powinienem podzielić swoje zadania? Myślałem o stworzeniu puli, która okresowo spawnuje procesory. Następnie, gdy procesor dojdzie do części, w której wywoła on owijki API, wrappery API uruchomią GreenPile, aby uzyskać aktualne dane HTTP za pomocą eventlet.green.urllib2. Czy to dobre podejście?

  3. Limity czasowe - chcę się upewnić, że żadne greenthreads nigdy się nie zawiesi. Czy to dobre podejście do ustawiania zdarzenia. Czas do 10-15 sekund na każde greenthread?

FYI, mam około 10 różnych zestawów danych w czasie rzeczywistym, a procesor jest odradzany co ~ 5-10 sekund.

Dzięki!

Odpowiedz

3

Nie uważam za właściwe mieszanie Flask/SQLAlchemy z asynchronicznym stylem programowania (lub sterowanym zdarzeniami).

Ponieważ jednak twierdzisz, że używasz RDBMS (MySQL) jako pamięci pośredniej, możesz po prostu utworzyć asynchronicznych pracowników, którzy przechowują wyniki z usług stron trzecich w RDMBS i zachować frontend (kolba/SQLAlchemy) synchroniczna?

W takim przypadku nie trzeba monkeypatch Flask ani SQLAlchemy.

Jeśli chodzi o szczegółowość, można użyć paradygmatu mapreduce do wykonywania wywołań i przetwarzania interfejsu API sieci Web. Ten wzorzec może dać ci pewien pomysł, jak logicznie oddzielić kolejne kroki i jak kontrolować zaangażowane procesy.

Osobiście nie użyłbym asynchronicznego środowiska do robienia tego. Lepszym rozwiązaniem może być użycie wieloprocesorowego, Celery lub prawdziwego systemu mapreduce, takiego jak Hadoop.

Wystarczy podpowiedź: zacznij od niewielkich rozmiarów, zachowaj prostotę i moduły, a następnie zoptymalizuj je później, jeśli potrzebujesz lepszej wydajności. Może to również w dużym stopniu wpływać na to, jak w czasie rzeczywistym chcesz uzyskać te informacje.

+0

dzięki za komentarz. Zgadzam się, aby nie mieszać Flask i Async I/O - nie musiało to być jasne z mojego pytania, ale API (Flask) działa na oddzielnym, niezlepionym, nie asynchronicznym procesie We/Wy. Grabger danych działa w procesie załatania, zapisując do db przy użyciu SQLAlchemy Core (nie ORM) tylko dla uproszczenia. – user1094786

+0

OK, w takim przypadku już to robisz w ten sposób. Zastanawiam się jednak, czy naprawdę potrzebujesz asynchronizacji dla grabbera danych. Może być lepiej z innymi metodami współbieżności (wieloprocesorowość, seler, itp.), Zwłaszcza jeśli twój grabber danych jest intensywnie wykorzystujący procesor. –

+0

+1 dla selera. Zadanie wygląda na to, że jest dobrym kandydatem. – Tisho

-1

Bezpiecznie jest łatać moduł napisany czystym pythonem i używając standardowej biblioteki lib.

  • istnieje kilka czystych adaptery MySQL:
  • PyMysql zawiera zestaw testowy sqlalchemy, można przeprowadzić test na swoich sprawach.
  • Istnieje moduł o nazwie pymysql_sa, aby zapewnić dialekt dla sqlalchemy
  • Flask jest napisany czystym pythonem i zgodnym z 100% WSGI 1.0. użyj usługi eventlet.wsgi w celu świadczenia usługi.

Podziel zadania przez pojedyncze pobranie przy użyciu zielonego modułu, jak tylko możesz. Umieść zadania w kolejce, która jest również dostarczana przez zdarzenie, każdy pracownik zadania pobiera zadanie z kolejki, a następnie zapisz wynik do db po zakończeniu pobierania lub wyślij obiekt Event.Event, aby uruchomić zadanie oczekujące na Zadanie zakończ. Lub oba procesy.

AKTUALIZACJA:

eventlet oficjalny dokument zalecamy używać plastra na linii pięści modułu głównego, i to jest bezpieczne, aby zadzwonić monkey_patch wielokrotnie. Więcej informacji na ten temat można znaleźć na stronie http://eventlet.net/doc/patching.html

Niektóre zielone moduły mogą pracować z wydarzeniem, wszystkie znajdują się w pliku eventlet.green. Lista na bitbucket. Upewnij się, że używasz zielonego modułu w kodzie lub załatuj go przed zaimportowaniem 3. modułów, które używają standardowych bibliotek.

Ale małpa akceptuje tylko kilka modułów, konieczne jest ręczne zaimportowanie zielonego modułu.

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)