Ricerca…


introduzione

In questo post discuteremo come è emerso il concetto di Eventloop e come può essere utilizzato per server ad alte prestazioni e applicazioni guidate da eventi come le GUI.

Come si è evoluto il concetto di event loop.

Eventloop in pseudo codice

Un ciclo di eventi è un ciclo che attende gli eventi e quindi reagisce a quegli eventi

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

Esempio di un server HTTP a thread singolo senza loop di eventi

    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)

Ecco una semplice forma di un server HTTP che è un singolo thread ma nessun ciclo di eventi. Il problema qui è che attende fino a quando ogni richiesta è terminata prima di iniziare a elaborare il successivo. Se è necessario un po 'di tempo per leggere le intestazioni delle richieste HTTP o per recuperare il file dal disco, dovremmo essere in grado di avviare l'elaborazione della richiesta successiva mentre attendiamo che finisca.

La soluzione più comune è rendere il programma multi-threaded.

Esempio di un server HTTP multi-thread con nessun ciclo di eventi

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)

Ora abbiamo reso il nostro piccolo server HTTP multi thread. In questo modo, possiamo passare immediatamente alla richiesta successiva perché la richiesta corrente è in esecuzione in un thread in background. Molti server, incluso Apache, utilizzano questo approccio.

Ma non è perfetto. Una limitazione è che puoi generare solo tanti thread. Per carichi di lavoro in cui si dispone di un numero enorme di connessioni, ma ogni connessione richiede solo l'attenzione di tanto in tanto, il modello multi-thread non funzionerà molto bene. La soluzione per questi casi è utilizzare un ciclo di eventi:

Esempio di un server HTTP con ciclo di eventi

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)

Speriamo che questo pseudocodice sia comprensibile. Ecco cosa sta succedendo: Aspettiamo che le cose accadano. Ogni volta che viene creata una nuova connessione o una connessione esistente richiede la nostra attenzione, ci occupiamo di essa, quindi torniamo ad aspettare. In questo modo, ci comportiamo bene quando ci sono molte connessioni e ognuna raramente richiede attenzione.

In un'applicazione reale (non pseudocodice) in esecuzione su Linux, la parte "aspetta che succeda l'evento successivo" sarebbe implementata chiamando la chiamata di sistema poll () o epoll (). Le parti "inizia a leggere / scrivere qualcosa su un socket" sarebbero implementate chiamando le chiamate di sistema recv () o send () in modalità non bloccante.

Riferimento:

[1]. "Come funziona un ciclo di eventi?" [In linea]. Disponibile: https://www.quora.com/How-does-an-event-loop-work



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow