2013-02-13 11 views
5

Próbuję służyć długo działającym żądaniom za pomocą gunicorn i jego asynchronicznych pracowników, ale nie mogę znaleźć żadnych przykładów, które mogę dostać do pracy. Użyłem przykład here ale manipulowane, aby dodać fałszywy opóźnienie (uśpienia do 5s) przed powrotem odpowiedź:gunicorn nie przetwarza jednoczesnych żądań jednocześnie

def app(environ, start_response): 
    data = "Hello, World!\n" 
    start_response("200 OK", [ 
     ("Content-Type", "text/plain"), 
     ("Content-Length", str(len(data))) 
    ]) 
    time.sleep(5) 
    return iter([data]) 

Potem biegnę gunicorn tak:

gunicorn -w 4 myapp:app -k gevent

Kiedy otwierają dwa przeglądarkę zakładki i wpisz http://127.0.0.1:8000/ w obu z nich i wysyłaj żądania prawie w tym samym czasie, żądania wydają się przetwarzane po kolei - jeden powraca po 5 sekundach, a drugi wraca po dalej 5 sekund.

P. Zgaduję, że sen nie jest przyjazny dla geodetów? Ale jest 4 pracowników i nawet jeśli typ pracownika był "zsynchronizowany", dwóch pracowników powinno obsługiwać jednocześnie dwa wnioski?

+0

Czy znalazłeś rozwiązanie? –

+0

Przepraszam, ja nie. – swoop81

Odpowiedz

5

Po prostu wpadłem na to samo, otworzyłem pytanie tutaj: Requests not being distributed across gunicorn workers. W rezultacie wygląda na to, że przeglądarka serializuje dostęp do tej samej strony. Zgaduję, że może to mieć coś wspólnego z cacheability, tzn. Przeglądarka myśli, że prawdopodobnie strona jest dostępna w pamięci podręcznej, poczekaj, aż załaduje dowiaduje się, że nie jest tak, że robi kolejną prośbę i tak dalej.

+0

Tak denerwujące i takie proste ... :( – jwg

+0

Dzięki @CrazyCasta, zweryfikowałem twoją odpowiedź, instalując inną przeglądarkę i wysyłając żądania z dwóch oddzielnych przeglądarek (chromium i firefox) jednocześnie, a żądania są obsługiwane równolegle – swoop81

0

Podaj gevent.sleep zamiast jednego strzału zamiast time.sleep.

To dziwne, że dzieje się to z -w 4, ale -k gevent jest typem asynchronicznego pracownika, więc możliwe jest, że gunicorn wysyła oba żądania do tego samego klienta. Zakładając, że tak się dzieje, time.sleep zablokuje twój proces, chyba że użyjesz gevent.monkey.patch_all().

1

Używając gunicorn z nie blokującym typem pracownika, np. Gevent, użyje TYLKO JEDNEGO procesu obsługującego zgłoszenia, więc nic dziwnego, że 5-sekundowa praca wykonywana jest sekwencyjnie.

Pracownik asynchroniczny jest przydatny, gdy obciążenie pracą jest lekkie, a szybkość żądania jest szybka, w takim przypadku gunicorn może wykorzystać czasy zmarnowane na oczekujące IO (np. Oczekiwanie na zapis do gniazda, aby zapisać odpowiedź) , , przełączając się do innego pracownika, aby wykonać inne żądanie. , przełączając się na inne żądanie przypisane temu samemu pracownikowi.

UPDATE

myliłem.

Podczas używania gunicorn z nie blokującym typem pracownika, z ustawieniami roboczymi w gunicorn, każdy pracownik jest procesem, który uruchamia oddzielną kolejkę.

Więc jeśli time.sleep został uruchomiony na innym procesie, uruchomi się jednocześnie, ale gdy zostanie uruchomiony w tym samym module, będzie wykonywany sekwencyjnie.

Problem polega na tym, że loadloader gunicorn mógł nie rozdzielić dwóch żądań na dwa procesy robocze. Bieżący proces można sprawdzić pod numerem os.getpid().

+0

Gunicorn nie używa tylko jednego procesu do obsługi żądań, używa numeru podanego jako flaga '-w" –

+0

@ ron.rothman To prawda! Moje wyjaśnienie jest błędne, dziękuję za wzmiankę. – tdihp

Powiązane problemy