Heim >Backend-Entwicklung >PHP-Tutorial >Detaillierte Erläuterung der Erkundung des PHP-FPM-Prozesspools

Detaillierte Erläuterung der Erkundung des PHP-FPM-Prozesspools

黄舟
黄舟Original
2017-10-18 09:25:122193Durchsuche

Der folgende Editor bietet Ihnen eine Erkundung des auf PHP-FPM basierenden Prozesspools. Der Herausgeber findet es ziemlich gut, deshalb werde ich es jetzt mit Ihnen teilen und es allen als Referenz geben. Folgen wir dem Editor, um einen Blick darauf zu werfen

PHP unterstützt Multiprozess, aber kein Multithreading; PHP-FPM führt mehrere untergeordnete Prozesse im Prozesspool aus, um alle Verbindungsanfragen gleichzeitig zu bearbeiten. Überprüfen Sie den Status des PHP-FPM-Prozesspools (pm.start_servers = 2) über ps wie folgt:


root@d856fd02d2fe:~# ps aux -L
USER  PID LWP %CPU NLWP %MEM VSZ RSS TTY  STAT START TIME COMMAND
root   1  1 0.0 1 0.0 4504 692 ?  Ss 13:10 0:00 /bin/sh /usr/local/php/bin/php-fpm start
root   7  7 0.0 1 0.4 176076 19304 ?  Ss 13:10 0:00 php-fpm: master process (/usr/local/php/etc/php-fpm.conf)
www-data  8  8 0.0 1 0.2 176076 8132 ?  S 13:10 0:00 php-fpm: pool www
www-data  9  9 0.0 1 0.2 176076 8132 ?  S 13:10 0:00 php-fpm: pool www
root  10 10 0.0 1 0.0 18376 3476 ?  Ss 14:11 0:00 bash
root  66 66 0.0 1 0.0 34420 2920 ?  R+ 15:13 0:00 ps aux -L

Wie aus der Liste ersichtlich ist , der Prozesspool www Es gibt zwei untergeordnete Prozesse PID 8 und PID 9, die noch inaktiv sind. Hinweis: NLWP bezieht sich auf die Anzahl der Lightweight-Prozesse, also die Anzahl der Threads.

Was ist PHP-FPM (FastCGI Process Manager)? PHP-FPM bietet eine Prozessverwaltungsmethode für PHP-CGI, mit der Speicher und Prozesse effektiv gesteuert und die PHP-Konfiguration reibungslos neu geladen werden können. Der Masterprozess befindet sich im Speicher. FastCGI ist eine sprachunabhängige, skalierbare offene CGI-Architekturerweiterung. Ihr Hauptverhalten besteht darin, den CGI-Interpreterprozess länger im Speicher zu halten, anstatt ihn zu forken und auszuführen, und so eine höhere Leistung zu erzielen. FastCGI unterstützt die verteilte Bereitstellung und kann auf mehreren Hosts außer dem WEB-Server bereitgestellt werden.

Zu untersuchende Methode: Simulieren Sie die gleichzeitige Ausführung mehrerer Threads

1. Was ist ein Thread: Threads werden manchmal auch als Lightweight-Prozesse (Lightweight) bezeichnet Der Prozess (LWP) besteht normalerweise aus der Thread-ID, dem aktuellen Befehlszeiger (PC), dem Registersatz und dem Stapel. Er ist eine Einheit im Prozess und die vom System unabhängig geplante Grundeinheit. Der Thread selbst besitzt keine Systemressourcen Einige laufen. Es teilt alle dem Prozess gehörenden Ressourcen mit anderen Threads, die zum selben Prozess gehören. Aufgrund der gegenseitigen Beschränkungen zwischen Threads weisen Threads Diskontinuität in ihrem Betrieb auf. Threads haben außerdem drei Grundzustände: bereit, blockiert und ausgeführt. Da der Prozess der Ressourceneigentümer ist, ist der Aufwand für das Erstellen, Abbrechen und Umschalten zu hoch. Daher ist die gleichzeitige Ausführung mehrerer Threads (Threads) auf einem symmetrischen Multiprozessor (SMP) eine geeignetere Wahl. Die Entität des Threads umfasst Programm, Daten und Thread-Kontrollblock (TCB). Wenn es nicht ausgeführt wird, werden vor Ort Ressourcen gespeichert


(3) eine Reihe von Ausführungsstapeln


(4) Hauptspeicher zum Speichern lokaler Variablen jedes Threads;


(5) Greifen Sie im selben Prozess auf den Hauptspeicher und andere Ressourcen zu.


Aber die Verwendung mehrerer Prozesse macht die Anwendung robuster für den Fall, dass ein Prozess im Prozesspool abstürzt oder angegriffen wird.


2. Multithreading simulieren:

Zusammenfassung der Erkundung: Ich führe das aus obiges Skript Schließlich habe ich einige Ergebnisse gefunden, die vorhersehbar waren, aber nicht das, was ich mir vorgestellt hatte


<?php
/**
 * PHP 只支持多进程不支持多线程。
 *
 * PHP-FPM 在进程池中运行多个子进程并发处理所有连接,
 * 同一个子进程可先后处理多个连接请求,但同一时间
 * 只能处理一个连接请求,未处理连接请求将进入队列等待处理
 *
 */

class SimulatedThread
{
 //模拟线程
 private $thread;

 //主机名
 private $host = &#39;tcp://172.17.0.5&#39;;

 //端口号
 private $port = 80;

 public function __construct()
 {
  //采用当前时间给线程编号
  $this->thread = microtime(true);
 }

 /**
  * 通过socket发送一个新的HTTP连接请求到本机,
  * 此时当前模拟线程既是服务端又是模拟客户端
  *
  * 当前(程序)子进程sleep(1)后会延迟1s才继续执行,但其持有的连接是继续有效的,
  * 不能处理新的连接请求,故这种做法会降低进程池处理并发连接请求的能力,
  * 类似延迟处理还有time_nanosleep()、time_sleep_until()、usleep()。
  * 而且sleep(1)这种做法并不安全,nginx依然可能出现如下错误:
  * “epoll_wait() reported that client prematurely closed connection,
  * so upstream connection is closed too while connecting to upstream”
  *
  * @return void
  */
 public function simulate()
 {
  $run = $_GET[&#39;run&#39;] ?? 0;
  if ($run++ < 9) {//最多模拟10个线程
   $fp = fsockopen($this->host, $this->port);
   fputs($fp, "GET {$_SERVER[&#39;PHP_SELF&#39;]}?run={$run}\r\n\r\n");
   sleep(1);//usleep(500)
   fclose($fp);
  }

  $this->log();
 }

 /**
  * 日志记录当前模拟线程运行时间
  *
  * @return void
  */
 private function log()
 {
  $fp = fopen(&#39;simulated.thread&#39;, &#39;a&#39;);
  fputs($fp, "Log thread {$this->thread} at " . microtime(true) . "(s)\r\n");

  fclose($fp);
 }
}

$thread = new SimulatedThread();
$thread->simulate();
echo "Started to simulate threads...";
1 PHP-FPM-Konfigurationselement pm.max_children = 5, simulierter.thread-Datensatz ist wie folgt :

Die zuletzt generierte (simulierte) Thread-Registrierung erscheint an der rot markierten Eintragsposition, da die maximale gleichzeitige Verbindungsverarbeitungskapazität des Prozesses erreicht ist Der Pool ist 5, daher ist dies nur möglich. Erscheint nach Artikel 6.


Log thread 1508054181.4236 at 1508054182.4244(s)
Log thread 1508054181.4248 at 1508054182.4254(s)
Log thread 1508054181.426 at 1508054182.428(s)
Log thread 1508054181.6095 at 1508054182.6104(s)
Log thread 1508054182.4254 at 1508054183.4262(s)
Log thread 1508054183.4272 at 1508054183.4272(s)
Log thread 1508054182.4269 at 1508054183.4275(s)
Log thread 1508054182.4289 at 1508054183.43(s)
Log thread 1508054182.6085 at 1508054183.6091(s)
Log thread 1508054182.611 at 1508054183.6118(s)

Interessant ist, dass die Registrierungszeit des (Simulations-)Threads, der durch den grünen Eintrag dargestellt wird, und des (Simulations-)Threads, der durch den roten Eintrag dargestellt wird, sind Dasselbe bedeutet, dass die beiden (Simulations-) Threads gleichzeitig ausgeführt werden.


Log thread 1508058075.042 at 1508058076.0428(s)
Log thread 1508058075.0432 at 1508058076.0439(s)
Log thread 1508058075.0443 at 1508058076.045(s)
Log thread 1508058075.6623 at 1508058076.6634(s)
Log thread 1508058076.0447 at 1508058077.0455(s)
Log thread 1508058076.046 at 1508058077.0466(s)
Log thread 1508058077.0465 at 1508058077.0466(s)
Log thread 1508058076.0469 at 1508058077.0474(s)
Log thread 1508058076.6647 at 1508058077.6659(s)
Log thread 1508058076.6664 at 1508058077.6671(s)
2. PHP-FPM-Konfigurationselement pm.max_children = 10, simulierter.thread wird wie folgt aufgezeichnet:

Da die Obergrenze der gleichzeitigen Verbindungsverarbeitungskapazität des Servers 10 erreicht, kann die zuletzt generierte (simulierte) Thread-Registrierung an jedem Ort erscheinen.


Log thread 1508061169.7956 at 1508061170.7963(s)
Log thread 1508061169.7966 at 1508061170.7976(s)
Log thread 1508061169.7978 at 1508061170.7988(s)
Log thread 1508061170.2896 at 1508061171.2901(s)
Log thread 1508061170.7972 at 1508061171.7978(s)
Log thread 1508061171.7984 at 1508061171.7985(s)
Log thread 1508061170.7982 at 1508061171.7986(s)
Log thread 1508061170.7994 at 1508061171.8(s)
Log thread 1508061171.2907 at 1508061172.2912(s)
Log thread 1508061171.2912 at 1508061172.2915(s)
3. Führen Sie die Verzögerung von usleep(500) aus. Der simulierte Thread-Datensatz lautet wie folgt:

Die sichtbare Protokollierungsreihenfolge stimmt mit der Reihenfolge überein, in der die (simulierten) Threads erzeugt wurden. Die Grundeinheit der USleep-Verzögerung ist Mikrosekunden (us, 1 s = 1000000 us).


Log thread 1508059270.3195 at 1508059270.3206(s)
Log thread 1508059270.3208 at 1508059270.3219(s)
Log thread 1508059270.322 at 1508059270.323(s)
Log thread 1508059270.323 at 1508059270.324(s)
Log thread 1508059270.3244 at 1508059270.3261(s)
Log thread 1508059270.3256 at 1508059270.3271(s)
Log thread 1508059270.3275 at 1508059270.3286(s)
Log thread 1508059270.3288 at 1508059270.3299(s)
Log thread 1508059270.3299 at 1508059270.331(s)
Log thread 1508059270.3313 at 1508059270.3314(s)
Wie aus den obigen Datensätzen ersichtlich ist:

1) Diese (simulierten) Threads werden nach der ersten Anforderung zur Ausführung automatisch generiert Skript, ein (Simulations-)Thread erstellt sofort einen anderen (Simulations-)Thread 2) Einige dieser (Simulations-)Threads werden im selben Unterprozessbereich generiert und ausgeführt; Das Zeitintervall zwischen der Generierung benachbarter (simulierter) Threads ist sehr kurz, fast gleichzeitig, oder der letzte (simulierte) Thread wird generiert, bevor die Ausführung des vorherigen (simulierten) Threads abgeschlossen ist

; 4) Mehrere (simulierte) Threads können gleichzeitig ausgeführt werden.

Die obige Implementierung der Simulation der Multithread-Parallelität ist also erfolgreich. Derselbe Unterprozess im PHP-FPM-Prozesspool kann mehrere Verbindungsanfragen nacheinander verarbeiten, jedoch nur eine Verbindungsanfrage gleichzeitig. Unverarbeitete Verbindungsanfragen werden in die Warteschlange gestellt und warten auf die Verarbeitung. Mit anderen Worten: Derselbe untergeordnete Prozess ist nicht in der Lage, Verbindungsanforderungen gleichzeitig zu verarbeiten.

PHP-FPM-Pool-Konfiguration: Ermöglicht die Definition mehrerer Pools, und jeder Pool kann unterschiedliche Konfigurationselemente definieren. Das Folgende ist nur eine Liste anderer Konfigurationselemente, auf die ich während meiner Erkundung geachtet habe

1. listen: Die Adresse, an der FastCGI-Anfragen angenommen werden sollen. Es werden zwei Kommunikationsprotokolle unterstützt: TCP-Socket und Unix-Socket. Sie können listen = [::]:9000 festlegen.

2. listen.allowed_clients: Liste der Adressen (IPv4/IPv6) von FastCGI-Clients, die eine Verbindung herstellen dürfen. Dieses Konfigurationselement ist eine durch Kommas getrennte Liste, z. B. listen.0.0.1,172.17 .0,5 .

15.00 Uhr: Wählen Sie aus, wie der Prozessmanager die Anzahl der untergeordneten Prozesse steuert. Dieses Konfigurationselement legt die Art und Weise fest, wie FPM den Prozesspool verwaltet, einschließlich statischer, dynamischer und On-Demand-Prozesse.

4. pm.max_requests: Die Anzahl der Anfragen, die jeder untergeordnete Prozess ausführen sollte, bevor er erneut erscheint. Dies kann nützlich sein, um Speicherlecks in Bibliotheken von Drittanbietern zu umgehen. Legen Sie die Obergrenze der Anzahl der von jedem verarbeiteten Anfragen fest Untergeordneter Prozess zur Verarbeitung. Nützlich bei Speicherlecks in Bibliotheken von Drittanbietern.

5. pm.status_path: Der URI zum Anzeigen der FPM-Statusseite.

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Erkundung des PHP-FPM-Prozesspools. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn