[LINUX] Welche Methode eignet sich am besten für die asynchrone Verarbeitung des TCP-Servers?

Früher konnte in Unix-basierten Systemen die E / A-Verarbeitung mit select () asynchron gemacht werden, und die Verarbeitung konnte nur durchgeführt werden, wenn sich der Status des Dateideskriptors änderte. Dies war (anscheinend) eine effektive Technik in einer Zeit, in der die Speicher- und Serverressourcen extrem niedrig waren. In der zweiten Hälfte der 90er und in der ersten Hälfte der 2000er Jahre wurde Multithreading zum Mainstream, und auf der Serverseite wurden Verbindungen gemultiplext, indem der Socket des Clients, der akzeptiert und akzeptiert wurde, an den Thread weitergeleitet und gesendet und empfangen wurde. (Natürlich war je nach Zweck auch asynchron aktiv)

Seit der zweiten Hälfte der 2000er Jahre macht das C10K-Problem Rauschen, und node.js und nginx sind aufgetreten. Die asynchrone Verarbeitung, die den Status von Deskriptoren überwacht, indem Sockets wieder nicht blockiert werden, wird mehr Aufmerksamkeit erregen als die Methode zum Erstellen einer großen Anzahl von Threads und zum Verbrauch von Ressourcen und Speicher. Und kürzlich sind Bibliotheken wie Javascript Promise, RX und Reactive Extension erschienen, die die asynchrone Verarbeitung an einem Ort in der Nähe der clientseitigen Benutzeroberfläche effizient beschreiben können.

Wenn jedoch eine asynchrone Verarbeitung auf der Serverseite in Betracht gezogen wird, ist es nicht möglich, Multi-Core- und Multi-CPU-Funktionen vollständig zu nutzen, indem nur asynchrone E / A-Vorgänge mit einem einzelnen Thread verarbeitet werden. Daher gibt es auch eine Methode, asynchron auf den Bereitschaftszustand des Sockets zu warten, nachdem dieser mit Accept () empfangen wurde. Wenn der Socket bereit ist, sendet und empfängt der Thread tatsächlich. Die asynchrone Verarbeitung selbst verfügt über mehrere Methoden wie select (), poll und epoll. Darüber hinaus gibt es zwei Methoden zum Multiplexen von Prozessen: Verwenden von Threads und Forking-Prozessen. Es gibt auch eine Methode, um Threads und Prozesse im Voraus zu erstellen und Daten an diese zu übergeben.

Methode verdienen デverdienen
select Reduzierter Speicher- und Ressourcenverbrauch Die Deskriptoren, die verarbeitet werden können, sind begrenzt
Andere Sockets können während der Sende- / Empfangsverarbeitung eines Sockets nicht verarbeitet werden
poll Reduzierter Speicher- und Ressourcenverbrauch
Keine Deskriptorgrenze
Andere Sockets können während der Sende- / Empfangsverarbeitung eines Sockets nicht verarbeitet werden
EPOLL Schnellere Version der Umfrage
Keine Deskriptorgrenze
Andere Sockets können während der Sende- / Empfangsverarbeitung eines Sockets nicht verarbeitet werden
fork Nicht viele Wartesteckdosen Hohe Prozesskosten
thread Nicht viele Wartesteckdosen Verbrauchen Sie die Kosten für die Thread-Erstellung und den Verbundstapelbereich
pre-fork Nicht viele Wartesteckdosen
Die Kosten für die Prozesserstellung fallen erst beim Start an
Bemühungen, Daten zu übertragen, die Verarbeitung zu sperren und Prozesse zu verwalten
pre-thread Nicht viele Wartesteckdosen
Die Kosten für die Thread-Erstellung fallen nur beim Start an
Bemühungen um Datenübertragung, Sperrverarbeitung und Thread-Verwaltung
EPOLL+thread Maximale Latenz bei gleichzeitiger Reduzierung des Speicher- und Ressourcenverbrauchs Kosten für die Thread-Erstellung. Bemühungen um Datenübertragung und Thread-Management
EPOLL+pre thread Maximale Latenz bei gleichzeitiger Reduzierung des Speicher- und Ressourcenverbrauchs Der Aufwand beim Übergeben von Daten und Verwalten von Threads ist komplizierter, aber wenn er gut implementiert ist, sollte er eine perfekte Leistung bieten.

Dieser Bereich ist "[Linux Network Programming Bible](http://www.amazon.co.jp/Linux Network Programming Bible-Mitsuyuki 1) ”ist detailliert.

Persönlich denke ich, dass "EPOLL + Thread" gut ist, aber gemäß den Benchmarks im obigen Buch hat "EPOLL + Thread" die schnellste Verbindungszeit, aber "Fork" hat die schnellste Übertragung und den schnellsten Empfang. Es scheint. In Bezug auf die Gesamtreihenfolge einschließlich der Verbindungszeit war "Pre-Thread" am schnellsten. Was das Senden und Empfangen betrifft, ist das Ergebnis, dass es schneller ist, "poll" und "EPOLL" normal zu verwenden, als spezielle Dinge wie Gabeln und Threads einschließlich "pre- ~" auszuführen (Stimmt das? ??). Übrigens steht geschrieben, dass "EPOLL + Thread" insgesamt 4. ist und langsamer als "select", "poll" und "EPOLL", aber dieses Ergebnis ist auch unglaublich.

Der Inhalt des Benchmarks scheint ein Experiment zu sein, bei dem 1000 Threads gestartet werden, indem der Verbindungsvorgang durch 50-maliges Senden und Empfangen wiederholt wird. Der Server ist ein Wählkern, und nur der send () -Teil wird eingefädelt oder gegabelt.

Wird sich die Leistung selbst dann verschlechtern, wenn Threads und Gabeln vorgeneriert sind, da Daten übertragen und Daten gesperrt werden? Ich denke, es ist durchaus möglich, dass der Punkt des Wählkerns einen Effekt hat (das Buch sagt auch, dass es sich um einen einfachen Vergleich ohne serverseitige Ressourcenüberwachung handelt).

Da "EPOLL + Pre-Thread" nicht eingeführt wird, kann dies am schnellsten sein, wenn die Anzahl der Threads in einer Multi-Core-Umgebung ordnungsgemäß unterdrückt wird. Wenn ich alleine schreibe, denke ich daran, die Anzahl der Threads mit "EPOLL + Pre-Thread" zu reduzieren.

Übrigens hat das Buch auch eine Methode zur Verarbeitung mehrerer Accepts selbst mit Threads eingeführt, aber ich kenne die Vor- und Nachteile dieser Methode nicht, da sie blockiert und einer von ihnen zum Empfänger wird.

Recommended Posts

Welche Methode eignet sich am besten für die asynchrone Verarbeitung des TCP-Servers?
Die Bildanzeigefunktion von iTerm ist praktisch bei der Verarbeitung von Bildern.
Warum ist der verteilte Ausdruck von Wörtern für die Verarbeitung natürlicher Sprache wichtig?
[Python] Anzahl der Ganzzahlzeichenfolgen der Länge n, für die die Summe m ist
Eine Methode zum Clustering von Punkten, die auf einer Hypersphäre verteilt sind. Dies ist praktisch für das Text Mining und die Merkmalsextraktion von Richtungsinformationen.