Maison  >  Article  >  développement back-end  >  Explication détaillée de l'exploration du pool de processus php-FPM

Explication détaillée de l'exploration du pool de processus php-FPM

黄舟
黄舟original
2017-10-18 09:25:122146parcourir

L'éditeur suivant vous proposera une exploration du pool de processus basé sur PHP-FPM. L'éditeur le trouve plutôt bon, je vais donc le partager avec vous maintenant et le donner comme référence pour tout le monde. Suivons l'éditeur pour jeter un coup d'œil

PHP prend en charge le multi-processus mais pas le multi-threading ; PHP-FPM exécute plusieurs processus enfants dans le pool de processus pour gérer toutes les demandes de connexion simultanément. Vérifiez l'état du pool de processus PHP-FPM (pm.start_servers = 2) via ps comme suit :


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

Comme le montre la liste , le pool de processus www Il existe deux processus enfants PID 8 et PID 9 qui sont toujours inactifs. Remarque : NLWP fait référence au nombre de processus légers, c'est-à-dire au nombre de threads.

Qu'est-ce que PHP-FPM (FastCGI Process Manager) ? PHP-FPM fournit une méthode de gestion de processus pour PHP-CGI, qui peut contrôler efficacement la mémoire et les processus, et recharger en douceur la configuration PHP. Son processus maître réside en mémoire. FastCGI est une extension ouverte CGI à architecture évolutive et indépendante du langage. Son comportement principal est de conserver le processus d'interprétation CGI en mémoire plus longtemps, plutôt que de le forker et de l'exécuter, et ainsi d'obtenir des performances plus élevées. FastCGI prend en charge le déploiement distribué et peut être déployé sur plusieurs hôtes autres que le serveur WEB.

Méthode à explorer : simuler une exécution simultanée multithread

1 Qu'est-ce qu'un thread : Les threads sont parfois aussi appelés processus légers (Lightweight. Processus, LWP), généralement composé d'un ID de thread, d'un pointeur d'instruction actuel (PC), d'un ensemble de registres et d'une pile, est une entité dans le processus et constitue l'unité de base planifiée indépendamment par le système. Le thread lui-même ne possède pas de ressources système, seulement ; certains en cours d'exécution partagent toutes les ressources appartenant au processus avec d'autres threads appartenant au même processus. En raison des contraintes mutuelles entre les threads, les threads présentent une discontinuité dans leur fonctionnement. Les threads ont également trois états de base : prêt, bloqué et en cours d'exécution. Étant donné que le processus est propriétaire de la ressource, les frais généraux de création, d'annulation et de commutation sont trop élevés, donc exécuter plusieurs threads (Threads) simultanément sur un multiprocesseur symétrique (SMP) est un choix plus approprié. L'entité du thread comprend le programme, les données et le bloc de contrôle du thread (TCB). Lorsqu'il n'est pas en cours d'exécution, ressources enregistrées sur site ;


(3) un ensemble de piles d'exécution


(4) mémoire principale pour stocker les variables locales de chaque thread ;


(5) Accédez à la mémoire principale et à d'autres ressources dans le même processus.


Mais l'utilisation de plusieurs processus rendra l'application plus robuste en cas de panne ou d'attaque d'un processus du pool de processus.


2. Simuler le multi-threading :

Résumé de l'exploration : je lance le script ci-dessus Enfin, j'ai trouvé des résultats prévisibles mais pas ceux auxquels j'avais pensé


<?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 L'élément de configuration PHP-FPM pm.max_children = 5, l'enregistrement simulé.thread est le suivant. :

Le dernier enregistrement de thread généré (simulé) apparaît dans la position d'entrée marquée en rouge car la capacité maximale de traitement des connexions simultanées du processus le pool est de 5, donc ce n'est possible qu'apparaît après l'article 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)

Ce qui est intéressant c'est que l'heure d'enregistrement du fil (de simulation) représenté par l'entrée verte et du fil (de simulation) représenté par l'entrée rouge sont les même, indiquant que les deux threads (simulation) sont exécutés simultanément.


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. Élément de configuration PHP-FPM pm.max_children = 10, simulation.thread est enregistré comme suit :

Étant donné que la limite supérieure de la capacité de traitement des connexions simultanées du serveur atteint 10, le dernier enregistrement de thread généré (simulé) peut apparaître à n'importe quel endroit.


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. Exécutez le délai usleep(500), l'enregistrement simulé.thread est le suivant :

L'ordre de journalisation visible est cohérent avec l'ordre dans lequel les threads (simulés) ont été générés. L'unité de base du délai de mise en veille est la microseconde (us, 1 s = 1 000 000 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)
Comme le montrent les enregistrements ci-dessus :

1) Ces threads (simulés) sont automatiquement générés après la première requête pour exécuter le script , un thread (de simulation) crée immédiatement un autre thread (de simulation) ; 2) Certains de ces threads (de simulation) sont générés et exécutés dans le même espace de sous-processus ; L'intervalle de temps entre la génération des threads adjacents (simulés) est très petit, presque en même temps, ou ce dernier thread (simulé) est généré avant que le thread précédent (simulé) ait fini de s'exécuter et de se fermer

; 4) Plusieurs threads (simulés) peuvent s’exécuter simultanément.

Ainsi, l'implémentation ci-dessus de simulation de concurrence multithread est réussie. Le même sous-processus dans le pool de processus PHP-FPM peut traiter plusieurs demandes de connexion successivement, mais ne peut traiter qu'une seule demande de connexion en même temps. Les demandes de connexion non traitées entreront dans la file d'attente et attendront d'être traitées. En d’autres termes, le même processus enfant n’a pas la capacité de gérer simultanément les demandes de connexion.

Configuration du pool PHP-FPM : elle permet de définir plusieurs pools, et chaque pool peut définir différents éléments de configuration. Ce qui suit n'est qu'une liste d'autres éléments de configuration auxquels j'ai prêté attention lors de mon exploration

1. écouter : L'adresse sur laquelle accepter les requêtes FastCGI. Il prend en charge deux protocoles de communication : TCP Socket et unix socket. Vous pouvez définir Listen = [::]:9000.

2. Listen.allowed_clients : Liste des adresses (IPv4/IPv6) des clients FastCGI autorisés à se connecter. Cet élément de configuration est une liste séparée par des virgules, telle que Listen.allowed_clients = 127.0.0.1,172.17. .0.5 .

15h : Choisissez comment le gestionnaire de processus contrôlera le nombre de processus enfants. Cet élément de configuration définit la façon dont FPM gère le pool de processus, y compris statique, dynamique et à la demande.

4. pm.max_requests : Le nombre de requêtes que chaque processus enfant doit exécuter avant de réapparaître. Cela peut être utile pour contourner les fuites de mémoire dans les bibliothèques tierces. Définir la limite supérieure du nombre de requêtes traitées par chacune. processus enfant, pour le traitement Utile pour les fuites de mémoire dans les bibliothèques tierces.

5. pm.status_path : L'URI pour afficher la page d'état FPM.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn