>  기사  >  백엔드 개발  >  PHP-FPM 프로세스 풀 탐색

PHP-FPM 프로세스 풀 탐색

一个新手
一个新手원래의
2017-10-17 09:11:372034검색

PHP는 멀티 프로세스를 지원하지만 멀티 스레딩은 지원하지 않습니다. PHP-FPM은 프로세스 풀에서 여러 하위 프로세스를 실행하여 모든 연결 요청을 동시에 처리합니다. 다음과 같이 ps를 통해 PHP-FPM 프로세스 풀(pm.start_servers = 2)의 상태를 확인합니다.


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

목록에서 볼 수 있듯이 프로세스 풀 www에는 두 개의 유휴 하위 프로세스가 있습니다. PID 8 및 PID 9. 참고: NLWP는 경량 프로세스 수, 즉 스레드 수를 나타냅니다.

PHP-FPM(FastCGI 프로세스 관리자)이란 무엇입니까? PHP-FPM은 메모리와 프로세스를 효과적으로 제어하고 PHP 구성을 원활하게 다시 로드할 수 있는 PHP-CGI용 프로세스 관리 방법을 제공합니다. FastCGI는 언어 독립적이고 확장 가능한 아키텍처인 CGI 개방형 확장입니다. 주요 동작은 포크 앤 실행이 아니라 더 오랜 시간 동안 CGI 인터프리터 프로세스를 메모리에 유지하여 더 높은 성능을 얻는 것입니다. FastCGI는 분산 배포를 지원하며 웹 서버 이외의 여러 호스트에 배포할 수 있습니다.

탐색 방법: 다중 스레드 동시 실행 시뮬레이션


1 스레드란 무엇입니까: 스레드는 경량 프로세스(Lightweight Process, LWP)라고도 하며 일반적으로 스레드 ID, 현재 명령으로 구성됩니다. 포인터(PC), 레지스터 세트 및 스택으로, 프로세스 내의 엔터티이며 시스템에 의해 독립적으로 스케줄링되는 기본 단위입니다. 스레드 자체는 시스템 리소스를 소유하지 않고 작동에 필수적인 일부 리소스만 소유합니다. 동일한 프로세스에 속하는 다른 리소스 스레드는 프로세스가 소유한 모든 리소스를 공유합니다. 스레드 간의 상호 제약으로 인해 스레드는 작업에 불연속성을 나타냅니다. 스레드에는 준비, 차단, 실행이라는 세 가지 기본 상태도 있습니다. 프로세스가 리소스 소유자이기 때문에 생성, 취소, 전환 오버헤드가 너무 높으므로 대칭형 다중 프로세서(SMP)에서 여러 스레드(스레드)를 동시에 실행하는 것이 더 적절한 선택입니다. 스레드 엔터티에는 프로그램, 데이터 및 스레드 제어 블록(TCB)이 포함됩니다.

(1) 스레드 상태

(2) 스레드가 실행되지 않을 때 저장된 현장 리소스

( 3) 실행 스택 세트,

(4) 각 스레드의 로컬 변수 메인 메모리를 저장합니다.

(5) 동일한 프로세스에서 메인 메모리와 기타 리소스에 액세스합니다.

그러나 여러 프로세스를 사용하면 프로세스 풀의 프로세스가 충돌하거나 공격을 받는 경우 애플리케이션이 더욱 강력해집니다.

2. 멀티 스레딩 시뮬레이션:


<?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 구성 항목 pm.max_children = 5,simulated.thread 기록은 다음과 같습니다.


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)

최근에 생성된(시뮬레이션된) 스레드 등록은 최대 동시 연결 처리 용량이 빨간색으로 표시된 항목 위치에 나타납니다. 프로세스 풀의 개수는 5 이므로 Article 6 이후에만 나타날 수 있습니다.


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 구성 항목 pm.max_children = 10,simulated.thread 기록은 다음과 같습니다.


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)

서버의 동시 접속 처리 용량 상한이 10에 도달하므로 가장 최근에 생성된(시뮬레이션된) 스레드 등록은 모든 위치에 나타날 수 있습니다.

3. usleep(500) 지연을 실행하면,simulated.thread 기록은 다음과 같습니다.


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)

로그 기록 순서가 (시뮬레이트된) 스레드 생성 순서와 일치함을 알 수 있습니다. usleep 지연의 기본 단위는 마이크로초(us, 1초 = 1000000us)입니다.

위 기록에서 볼 수 있습니다.

1) 이 (시뮬레이션) 스레드는 스크립트를 실행하기 위한 첫 번째 요청 후에 자동으로 생성됩니다. 하나의 (시뮬레이션) 스레드가 또 다른 (시뮬레이션) 스레드를 생성합니다.

2) 이러한 (시뮬레이션) 스레드 중 일부는 동일한 하위 프로세스 공간에서 생성되고 실행됩니다.

3) 인접한(시뮬레이션) 스레드 간의 생성 시간 간격은 매우 작습니다. 또는 이전(시뮬레이트된) 스레드가 실행을 마치고 종료되기 전에 후자(시뮬레이트된) 스레드가 생성됩니다

4) 여러(시뮬레이트된) 스레드가 동시에 실행될 수 있습니다.

그래서 위의 다중 스레드 동시성 시뮬레이션 구현은 성공적입니다.

PHP-FPM 프로세스 풀의 동일한 하위 프로세스는 여러 연결 요청을 연속적으로 처리할 수 있지만 동시에 하나의 연결 요청만 처리할 수 있습니다. 처리되지 않은 연결 요청은 대기열에 들어가 처리를 기다립니다. 즉, 동일한 하위 프로세스에는 연결 요청을 동시에 처리할 수 있는 기능이 없습니다.

PHP-FPM 풀 구성: 여러 풀을 정의할 수 있으며 각 풀은 서로 다른 구성 항목을 정의할 수 있습니다. 다음은 제가 탐색하는 동안 주의를 기울인 기타 구성 항목의 목록입니다


  1. listen: FastCGI 요청을 수락하는 주소입니다. TCP 소켓과 Unix 소켓이라는 두 가지 통신 프로토콜을 지원합니다. 청취 = [::]:9000을 설정할 수 있습니다.

  2. listening.allowed_clients: 연결이 허용된 FastCGI 클라이언트의 주소(IPv4/IPv6) 목록입니다. 이 구성 항목은 쉼표로 구분된 목록입니다(예: listening.allowed_clients = 127.0.0.1,172.17.0.5). .

  3. pm: 프로세스 관리자가 하위 프로세스 수를 제어하는 ​​방법을 선택합니다. 이 구성 항목은 FPM이 정적, 동적 및 온디맨드를 포함하여 프로세스 풀을 관리하는 방식을 설정합니다.

  4. pm.max_requests: 각 하위 프로세스가 다시 생성되기 전에 실행해야 하는 요청 수입니다. 이는 타사 라이브러리의 메모리 누수 문제를 해결하는 데 유용할 수 있습니다.

  5. pm.status_path: FPM 상태 페이지를 보기 위한 URI입니다.

위 내용은 PHP-FPM 프로세스 풀 탐색의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.