Ich versuche, die niedrigeren Details von Webservern zu verstehen. Ich frage mich, ob ein Server, wie Apache, ständig nach neuen Anfragen fragt oder ob er von einem Interrupt-System funktioniert. Wenn es sich um einen Interrupt handelt, was löst den Interrupt aus, ist es der Netzwerkkartentreiber?
networking
webserver
embedded
user2202911
quelle
quelle
Antworten:
Die kurze Antwort lautet: eine Art Interrupt-System. Im Wesentlichen verwenden sie blockierende E / A, dh sie schlafen (blockieren), während sie auf neue Daten warten.
Der Server erstellt einen Listening-Socket und blockiert ihn, während er auf neue Verbindungen wartet. Während dieser Zeit versetzt der Kernel den Prozess in einen unterbrechbaren Ruhezustand und führt andere Prozesse aus. Dies ist ein wichtiger Punkt: Wenn die Prozessabfrage kontinuierlich durchgeführt wird, wird die CPU verschwendet. Der Kernel kann die Systemressourcen effizienter nutzen, indem er den Prozess blockiert, bis Arbeit für ihn zu erledigen ist.
Wenn neue Daten im Netzwerk ankommen, gibt die Netzwerkkarte einen Interrupt aus.
Nachdem die Netzwerkkarte unterbrochen wurde, liest der Kernel über den Netzwerkkartentreiber die neuen Daten von der Netzwerkkarte und speichert sie im Speicher. (Dies muss schnell erledigt werden und wird im Allgemeinen im Interrupt-Handler erledigt.)
Der Kernel verarbeitet die neu eingetroffenen Daten und ordnet sie einem Socket zu. Ein Prozess, der auf diesem Socket blockiert wird, wird als ausführbar markiert, was bedeutet, dass er jetzt ausgeführt werden kann. Es wird nicht unbedingt sofort ausgeführt (der Kernel entscheidet sich möglicherweise dafür, noch andere Prozesse auszuführen).
In seiner Freizeit wird der Kernel den blockierten Webserver-Prozess aktivieren. (Da es jetzt lauffähig ist.)
Der Webserver-Prozess wird so ausgeführt, als ob keine Zeit verstrichen wäre. Sein blockierender Systemaufruf kehrt zurück und verarbeitet alle neuen Daten. Fahren Sie dann mit Schritt 1 fort.
quelle
accept
. Sie sind (zum Glück, oder es wäre total beschissen!) Unabhängige, asynchron laufende Aufgaben. Wenn Verbindungen eingehen, werden sie in eine Warteschlange gestellt, aus der sie abgerufen werdenaccept
. Nur wenn es keine gibt, blockiert es.Es gibt ziemlich viele "niedrigere" Details.
Stellen Sie sich zunächst vor, der Kernel verfügt über eine Liste von Prozessen. Einige dieser Prozesse werden zu einem bestimmten Zeitpunkt ausgeführt, andere nicht. Der Kernel lässt jedem laufenden Prozess einen Teil der CPU-Zeit zu, unterbricht ihn dann und wechselt zum nächsten. Wenn es keine ausführbaren Prozesse gibt, gibt der Kernel wahrscheinlich eine Anweisung wie HLT an die CPU aus, die die CPU anhält, bis ein Hardware-Interrupt auftritt.
Irgendwo auf dem Server befindet sich ein Systemaufruf mit der Aufschrift "Gib mir etwas zu tun". Es gibt zwei Kategorien von Möglichkeiten, wie dies durchgeführt werden kann. Im Fall von Apache ruft es
accept
einen Socket auf, den Apache zuvor geöffnet hat, und überwacht wahrscheinlich Port 80. Der Kernel verwaltet eine Warteschlange mit Verbindungsversuchen und fügt diese Warteschlange jedes Mal hinzu, wenn ein TCP-SYN empfangen wird. Wie der Kernel weiß, dass eine TCP-SYN empfangen wurde, hängt vom Gerätetreiber ab. Bei vielen Netzwerkkarten liegt wahrscheinlich ein Hardware-Interrupt vor, wenn Netzwerkdaten empfangen werden.accept
bittet den Kernel, mir den nächsten Verbindungsaufbau zurückzugeben. Wenn die Warteschlange nicht leer war,accept
kehrt sie sofort zurück. Wenn die Warteschlange leer ist, wird der Prozess (Apache) aus der Liste der ausgeführten Prozesse entfernt. Wenn später eine Verbindung hergestellt wird, wird der Vorgang fortgesetzt. Dies wird als "Blockieren" bezeichnet, da der aufrufende Prozessaccept()
wie eine Funktion aussieht, die erst zurückkehrt, wenn ein Ergebnis vorliegt, das in einiger Zeit vorliegen könnte. Während dieser Zeit kann der Prozess nichts anderes tun.Nach der
accept
Rückkehr weiß Apache, dass jemand versucht, eine Verbindung herzustellen. Anschließend wird fork aufgerufen , um den Apache-Prozess in zwei identische Prozesse aufzuteilen. Einer dieser Prozesse verarbeitet die HTTP-Anforderung, der andere ruftaccept
erneut auf, um die nächste Verbindung herzustellen. Daher gibt es immer einen Master-Prozess, der nuraccept
Unterprozesse aufruft und erzeugt, und dann gibt es für jede Anforderung einen Unterprozess.Dies ist eine Vereinfachung: Es ist möglich, dies mit Threads anstelle von Prozessen zu tun, und es ist auch möglich, dies
fork
vorher zu tun, damit ein Arbeitsprozess bereit ist, wenn eine Anforderung empfangen wird, wodurch der Startaufwand verringert wird. Abhängig davon, wie Apache konfiguriert ist, kann es eines dieser Dinge tun.Dies ist die erste allgemeine Kategorie, und sie wird als E / A- Blockierung bezeichnet, da Systemaufrufe wie
accept
undread
undwrite
, die auf Sockets ausgeführt werden, den Prozess anhalten, bis sie etwas zurückgeben können.Der andere breite Weg, dies zu tun, wird als nicht blockierende oder ereignisbasierte oder asynchrone E / A bezeichnet . Dies wird mit Systemaufrufen wie
select
oder implementiertepoll
. Diese tun jeweils dasselbe: Sie geben ihnen eine Liste von Sockets (oder allgemein Dateideskriptoren) und was Sie damit tun möchten, und der Kernel blockiert, bis er bereit ist, eines dieser Dinge zu tun.Bei diesem Modell können Sie dem Kernel (mit
epoll
) mitteilen : "Sagen Sie mir, wenn eine neue Verbindung an Port 80 besteht oder wenn neue Daten auf einer dieser 9471 anderen Verbindungen gelesen werden sollen, die ich geöffnet habe".epoll
blockiert, bis eines dieser Dinge fertig ist, dann machst du es. Dann wiederholst du. Systemaufrufe mögenaccept
undread
und werdenwrite
niemals blockiert, zum Teil, weil Sie bei jedem Aufrufepoll
nur erfahren haben, dass sie bereit sind, sodass es keinen Grund zum Blockieren gibt, und weil Sie beim Öffnen des Sockets oder der von Ihnen angegebenen Datei angeben, dass Sie sie möchten Im nicht blockierenden Modus schlagen diese Anrufe fehl,EWOULDBLOCK
anstatt zu blockieren.Der Vorteil dieses Modells ist, dass Sie nur einen Prozess benötigen. Dies bedeutet, dass Sie nicht für jede Anforderung eine Stapel- und Kernelstruktur zuweisen müssen. Nginx und HAProxy verwenden dieses Modell und es ist ein großer Grund, warum sie mit so viel mehr Verbindungen als Apache auf ähnlicher Hardware umgehen können.
quelle