Workerman ist ein Open-Source-Hochleistungs-Asynchron-PHP-Socket-Framework, das ausschließlich in PHP entwickelt wurde. Unterstützt lange TCP-Verbindungen und viele Protokolle wie Websocket und MQTT. Heute werden wir das reusePort-Attribut in Workerman einführen. Sie können bei Bedarf darauf verweisen.
Workerman ist ein leistungsstarkes PHP-Socket-Server-Framework. Sie können Workerman verwenden, um direkt auf der TCP-Ebene zu programmieren. Die grundlegende Programmierroutine lautet:
$w = new Workerman\Worker('tcp://0.0.0.0:80'); $w->count = 4; $w->onMessage = function(Workerman\COnnection\TcpConnection $connection, array $data) { $connection->send('Hello World'); }; Worker::runAll();
Ich frage mich, ob Ihnen der Parameter reusePort aufgefallen ist. Er ist standardmäßig auf false gesetzt. Wozu dient dieser Parameter? Unter welchen Umständen müssen wir es auf „true“ setzen, um die Leistung zu verbessern? 1. Die Rolle von Reuseport
Wenn Sie sich nicht eingehend mit der Linux-Netzwerkprogrammierung befasst haben, ist es schwierig, diesen Satz zu verstehen. Hier eine kurze Erklärung:
Das Serverprogramm empfängt normalerweise Clientanfragen, indem es eine bestimmte Portnummer auf dem Server abhört. Unter Linux werden die Netzwerkkarte des Servers und die Portnummer in einen
Socketabstrahiert. Um die Leistung zu verbessern, verfügen allgemeine Serverprogramme über mehrere Prozesse (allgemein bekannt als
Worker), die bei der Ausführung denselben Socket überwachen. Wenn keine Clientverbindung eintrifft, befinden sich diese Worker in einem angehaltenen Zustand und verbrauchen keine CPU-Ressourcen. Wenn zu einem bestimmten Zeitpunkt eine Client-Verbindung eintrifft, weckt der Linux-Kernel diese Worker gleichzeitig und lässt sie um die Verarbeitung der Verbindung konkurrieren.
Dadurch erhält nur ein Worker die Möglichkeit, die Verbindung zu verwalten , und die anderen Arbeiter werden nach dem Scheitern des Wettbewerbs in den suspendierten Zustand zurückkehren. Der Prozess des Aufweckens eines Workers verbraucht CPU-Ressourcen. Je größer die Anzahl der Worker, desto mehr CPU-Ressourcen werden verbraucht, was zu einer Ressourcenverschwendung führt. Dies wird oft als „Thundering Herd Effect“ bezeichnet.
Sie fragen sich vielleicht: Warum nicht jeweils einen Arbeiter aufwecken? Leider verfügt der Linux-Kernel nicht über eine solche Funktion. Glücklicherweise wurde die Reuseport-Funktion zu Linux 3.9 und späteren Versionen hinzugefügt. Wozu dient diese Funktion?
Vor Reuseport konnte eine Portnummer nur von einem Socket überwacht werden. Mit Reuseport wird diese Einschränkung aufgehoben: Eine Portnummer kann von mehreren Sockets gleichzeitig überwacht werden.
Wie bereits erwähnt, kann der Linux-Kernel nicht jeweils nur einen Worker aktivieren, aber der Kernel kann Client-Verbindungen gleichmäßig an eine Gruppe von Sockets senden, die denselben Port überwachen.
Wie in der Abbildung gezeigt, verfügt jeder Worker über einen eigenen Socket, der alle am selben Port lauscht. Wenn eine Client-Verbindung eintrifft, leitet der Kernel die Verbindung an einen Socket weiter, und dieser Socket weckt nur den Worker, zu dem er gehört. Dadurch wird der „Thundering Herd Effect“ geschickt gelöst und die Gesamtleistung verbessert.
Daraus können wir schließen: Wenn Ihre Linux-Kernelversion 3.9 und höher ist, können Sie bei Verwendung von Workerman reusePort auf true setzen, um die Effizienz der Programmausführung zu verbessern.
2. Wie Workerman reuseport verwendetObwohl Sie reusePort in Workerman nur auf
truesetzen müssen, können Sie diese erweiterte Funktion von Linux nutzen. Aber im Quellcode von Workerman ist es nicht nur so einfach, einen Kernel-Parameter zu aktivieren. Workerman verbirgt viele Designdetails für Sie, werfen wir einen Blick darauf.
Worker
-Klasse ist die wichtigste Klasse in Workerman. Es gibt eine listen()
-Funktion: protected function listen() { ... if (!$this->_mainSocket) { ... $this->_mainSocket = stream_socket_server(...); ... } ... }
listen()
-Funktion Einfach erstellen Erstellen Sie einen Socket im aktuellen Prozess und beginnen Sie, auf Anfragen zu warten. Wenn reusePort
ist, ruft der Hauptprozess die Funktion listen()
auf, bevor er den Worker erstellt: Worker
类是 Workerman 里最主要的类,其中有个 listen()
函数:
protected function initWorkers() { .... if (!$worker->reusePort) { $worker->listen(); } .... }
listen()
函数的作用就是在当前进程创建一个 Socket 并开始监听请求。
当 reusePort 为 false 时,主进程在创建 Worker 之前就调用了 listen()
函数:
protected static function forkOneWorkerForLinux($worker) { ... $pid = pcntl_fork(); if ($pid === 0) { if ($worker->reusePort) { $worker->listen(); } ... } ... }
随后主进程通过 pcntl_fork() 创建 Worker。pcntl_fork() 有个特性:创建出来的子进程(Worker)中的变量都是父进程复制而来的,包括父进程创建的 mainSocket。所以,当reusePort为∗∗false∗∗时,所有的Worker都复制父进程的mainSocket。所以,当reusePort为∗∗false∗∗时,所有的Worker都复制父进程的_mainSocket,也即共用一个 Socket。
而当 reusePort 为 true 时,情况就不同了。主进程在创建 Worker 前不会调用 listen()
,而是在创建完 Worker 后由每个 Worker 自行发起 listen()
if ($this->reusePort) { $context = stream_context_create(); stream_context_set_option($context, 'socket', 'so_reuseport', 1); }
wahr
ist, ist die Situation anders. Der Hauptprozess ruftlisten()
nicht auf, bevor er einen Worker erstellt. Stattdessen initiiert jeder Worker nach dem Erstellen eines Workers einen listen()
-Aufruf: 🎜rrreee🎜 Das Ergebnis ist, dass jeder untergeordnete Prozess (Worker) seinen eigenen Socket erstellt. 🎜🎜Eine letzte Sache: Wenn Sie möchten, dass der Kernel die Wiederverwendungsfunktion aktiviert, müssen Sie den Socket-Kontext manuell festlegen: 🎜if ($this->reusePort) { $context = stream_context_create(); stream_context_set_option($context, 'socket', 'so_reuseport', 1); }
推荐学习:php视频教程
Das obige ist der detaillierte Inhalt vonDas Attribut reusePort in Workerman, das Sie kennen müssen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!