Szukaj…


Wprowadzenie

W tym poście omówimy, w jaki sposób pojawiła się koncepcja Eventloop i jak można jej używać w serwerach o wysokiej wydajności i aplikacjach sterowanych zdarzeniami, takich jak GUI.

Jak ewoluowała koncepcja pętli zdarzeń.

Eventloop w pseudo-kodzie

Pętla zdarzeń to pętla, która czeka na zdarzenia, a następnie reaguje na te zdarzenia

while true:
    wait for something to happen
    react to whatever happened

Przykład jednowątkowego serwera HTTP bez pętli zdarzeń

    while true:
    socket = wait for the next TCP connection
    read the HTTP request headers from (socket)
    file_contents = fetch the requested file from disk
    write the HTTP response headers to (socket)
    write the (file_contents) to (socket)
    close(socket)

Oto prosta forma serwera HTTP, który jest jednowątkowy, ale nie ma pętli zdarzeń. Problem polega na tym, że przed rozpoczęciem przetwarzania następnego czeka, aż każde żądanie zostanie zakończone. Jeśli odczytanie nagłówków żądań HTTP lub pobranie pliku z dysku zajmuje trochę czasu, powinniśmy być w stanie rozpocząć przetwarzanie następnego żądania w oczekiwaniu na jego zakończenie.

Najczęstszym rozwiązaniem jest uczynienie programu wielowątkowym.

Przykład wielowątkowego serwera HTTP bez pętli zdarzeń

function handle_connection(socket):
    read the HTTP request headers from (socket)
    file_contents = fetch the requested file from disk
    write the HTTP response headers to (socket)
    write the (file_contents) to (socket)
    close(socket)
while true:
    socket = wait for the next TCP connection
    spawn a new thread doing handle_connection(socket)

Teraz nasz mały serwer HTTP jest wielowątkowy. W ten sposób możemy natychmiast przejść do następnego żądania, ponieważ bieżące żądanie działa w wątku w tle. Wiele serwerów, w tym Apache, korzysta z tego podejścia.

Ale to nie jest idealne. Jednym ograniczeniem jest to, że możesz spawnować tylko tyle wątków. W przypadku obciążeń, w których istnieje ogromna liczba połączeń, ale każde połączenie wymaga uwagi tylko raz na jakiś czas, model wielowątkowy nie będzie działał zbyt dobrze. Rozwiązaniem tych przypadków jest użycie pętli zdarzeń:

Przykład serwera HTTP z pętlą zdarzeń

while true:
    event = wait for the next event to happen
    if (event.type == NEW_TCP_CONNECTION):
        conn = new Connection
        conn.socket = event.socket
        start reading HTTP request headers from (conn.socket) with userdata = (conn)
    else if (event.type == FINISHED_READING_FROM_SOCKET):
        conn = event.userdata
        start fetching the requested file from disk with userdata = (conn)
    else if (event.type == FINISHED_READING_FROM_DISK):
        conn = event.userdata
        conn.file_contents = the data we fetched from disk
        conn.current_state = "writing headers"
        start writing the HTTP response headers to (conn.socket) with userdata = (conn)
    else if (event.type == FINISHED_WRITING_TO_SOCKET):
        conn = event.userdata
        if (conn.current_state == "writing headers"):
            conn.current_state = "writing file contents"
            start writing (conn.file_contents) to (conn.socket) with userdata = (conn)
        else if (conn.current_state == "writing file contents"):
            close(conn.socket)

Mam nadzieję, że ten pseudokod jest zrozumiały. Oto, co się dzieje: czekamy, aż coś się wydarzy. Za każdym razem, gdy tworzone jest nowe połączenie lub istniejące połączenie wymaga naszej uwagi, zajmujemy się tym, a następnie wracamy do oczekiwania. W ten sposób osiągamy dobre wyniki, gdy jest wiele połączeń i każde z nich rzadko wymaga uwagi.

W prawdziwej aplikacji (nie pseudokodowej) działającej w systemie Linux część „czekać na następne zdarzenie” zostanie zaimplementowana poprzez wywołanie systemowe poll () lub epoll (). Części „zacznij czytać / zapisywać coś w gnieździe” zostaną zaimplementowane poprzez wywołanie wywołań systemowych recv () lub send () w trybie nieblokującym.

Odniesienie:

[1] „Jak działa pętla zdarzeń?” [Online]. Dostępne: https://www.quora.com/How-does-an-event-loop-work



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow