Maison >développement back-end >tutoriel php >Explorer le pool de processus PHP-FPM
PHP prend en charge le multi-processus mais pas le multi-threading ; PHP-FPM exécute plusieurs sous-processus dans le pool de processus pour gérer toutes les demandes de connexion simultanément. Affichez 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 on peut le voir dans la liste, le processus Il y a deux processus enfants PID 8 et PID 9 qui sont toujours inactifs dans le pool www. 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éthodes d'exploration : Simuler une exécution simultanée multithread
1 Qu'est-ce qu'un thread : Les threads sont parfois un processus léger (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 le système ; Les ressources ne disposent que de quelques ressources essentielles au fonctionnement et 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é. Les entités de thread incluent les programmes, les données et les blocs de contrôle de thread (TCB). TCB comprend les informations suivantes :
(1) État du thread
(2) Lorsque le thread n'est pas en cours d'exécution, enregistré sur ; -ressources du site ;
(3) un ensemble de piles d'exécution
(4) stockage des variables locales de chaque thread dans la mémoire principale
(5) accès principal ; mémoire et 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. Simulation du multi-threading :
<?php /** * PHP 只支持多进程不支持多线程。 * * PHP-FPM 在进程池中运行多个子进程并发处理所有连接, * 同一个子进程可先后处理多个连接请求,但同一时间 * 只能处理一个连接请求,未处理连接请求将进入队列等待处理 * */ class SimulatedThread { //模拟线程 private $thread; //主机名 private $host = 'tcp://172.17.0.5'; //端口号 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['run'] ?? 0; if ($run++ < 9) {//最多模拟10个线程 $fp = fsockopen($this->host, $this->port); fputs($fp, "GET {$_SERVER['PHP_SELF']}?run={$run}\r\n\r\n"); sleep(1);//usleep(500) fclose($fp); } $this->log(); } /** * 日志记录当前模拟线程运行时间 * * @return void */ private function log() { $fp = fopen('simulated.thread', 'a'); fputs($fp, "Log thread {$this->thread} at " . microtime(true) . "(s)\r\n"); fclose($fp); } } $thread = new SimulatedThread(); $thread->simulate(); echo "Started to simulate threads...";
Résumé d'exploration : Après avoir exécuté le script ci-dessus, j'ai trouvé des résultats prévisibles mais pas ceux auxquels j'avais pensé
1. Élément de configuration PHP-FPM pm.max_children =. 5, l'enregistrement simulé.thread est le suivant :
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)
Le dernier enregistrement de fil généré (simulé) apparaît dans la position d'entrée marquée en rouge en raison de traitement de connexion simultanée du pool de processus Le plafond de capacité est de 5, il ne peut donc apparaître que dans l'article 6 et au-delà.
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)
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 chose, indiquant que les deux threads (simulation) sont exécutés simultanément.
2. Élément de configuration PHP-FPM pm.max_children = 10, l'enregistrement simulé.thread est le suivant :
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)
En raison de la connexion simultanée capacité de traitement du serveur La limite supérieure est jusqu'à 10, de sorte que le dernier enregistrement de thread généré (simulé) peut apparaître n'importe où.
3. Exécutez le délai usleep(500), l'enregistrement simulé.thread est le suivant :
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)
On peut voir que la séquence d'enregistrement du journal est généré par le thread (simulé). L'ordre est cohérent. L'unité de base du délai de mise en veille est la microseconde (us, 1 s = 1 000 000 us).
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 d'exécution du script, un (simulé) Le thread crée ensuite un autre thread (simulation)
2) Certains de ces threads (simulation) sont dans le même sous-processus ; space Généré et exécuté dans
3) L'intervalle de temps entre la génération des threads adjacents (simulation) est très petit, presque en même temps, ou le dernier (simulation) Le thread est généré avant que le thread précédent (simulé) ait fini de s'exécuter et de se terminer
4) Plusieurs threads (simulés) peuvent être exécutés 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 gérer plusieurs demandes de connexion successivement, mais une seule demande de connexion peut être traitée en même temps. Les demandes de connexion non traitées entreront dans la file d'attente et attendront leur traitement. 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 : Il 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 de quelques autres éléments de configuration auxquels j'ai prêté attention pendant le processus d'exploration
é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.
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, par exemple. comme écoute .allowed_clients = 127.0.0.1,172.17.0.5.
pm : 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 Trois types.
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éfinies par. Une limite supérieure du nombre de requêtes traitées par un sous-processus, utile pour gérer les fuites de mémoire dans les bibliothèques tierces.
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!