【问题标题】:Whether the connection between php-fpm and nginx by fast-cgi are persistent (keep-alive) connection?php-fpm 和 nginx 通过 fast-cgi 的连接是否是持久(keep-alive)连接?
【发布时间】:2017-09-02 23:35:30
【问题描述】:

我正在尝试编写一个服务器演示来连接 php-fpm ,但我不知道 fast-cgi 与 php-fpm 和 nginx 之间的连接是否是持久(keep-alive)连接? 每次向 nginx 发出 http 请求时,nginx 会再次通过 tcp 3-Way Handshake 连接 php-fpm 吗?或者 nginx 和 php-fpm 之间的连接是 keep-alive 连接,nginx 尝试重用它?

【问题讨论】:

  • 我看到一个声明,但没有问题
  • @RiggsFolly 也许有点苛刻?对我来说似乎很清楚这个问题是 php-fpm 和 nginx 之间通过 fast-cgi 的连接是持久(保持活动)连接吗?
  • 客户端连接服务器,向nginx发送请求,nginx可能要求PHP-FPM处理(通过fcgi),PHP处理并产生响应,PHP给nginx响应,PHP -FPM 完成并与 nginx 断开连接。之后发生的一切都在 nginx 和客户端之间。
  • 不,php-fpmnginx 不会在请求发送后断开连接。连接将持续存在。
  • @Mjh FPM 线程保持活动状态的事实并不意味着与 nginx 的连接也保持活动状态。并没有你想的那么浪费。通常发生的情况是,操作系统不会在请求时立即关闭连接,而是在资源允许的情况下将它们暂停,这意味着重新连接成本最小,同时技术上终止连接。请记住,套接字连接是操作系统的有限资源,因此将正在使用的连接最小化是最佳策略。

标签: php sockets nginx


【解决方案1】:

PHP-FPM 是 fastCGI 协议的实现,因此它遵守所有 fastCGI 规范要求。

section 3.5 of the specification 中有一个这样的要求,特别是关于关闭连接:

Web 服务器控制传输连接的生命周期。当没有请求处于活动状态时,Web 服务器可以关闭连接。或者,Web 服务器可以将关闭权限委托给应用程序(请参阅 FCGI_BEGIN_REQUEST)。在这种情况下,应用程序在指定请求结束时关闭连接。 这种灵活性适用于各种应用风格。简单的应用程序将一次处理一个请求,并为每个请求接受一个新的传输连接。更复杂的应用程序将通过一个或多个传输连接处理并发请求,并将长时间保持传输连接打开。

一个简单的应用程序通过在完成写入响应后关闭传输连接来获得显着的性能提升。 Web 服务器需要控制长连接的连接生命周期。

当应用关闭连接或发现连接已关闭时,应用启动新连接。

这意味着由网络服务器决定连接是否持续。这是通过 fastcgi_keep_conn 选项在 nginx 中实现的,该选项声明:

默认情况下,FastCGI 服务器会在发送响应后立即关闭连接。然而,当这个指令设置为 on 时,nginx 将指示 FastCGI 服务器保持连接打开。这对于与 FastCGI 服务器的 keepalive 连接发挥作用尤其重要。

此声明是为了反映规范行为以及网络服务器可以提供 fastCGI 生成的内容以修改默认行为的能力。

我在这里的假设是,保持连接没有任何意义,因为网络服务器的线程不断被回收。也许有指定数量的停放线程,但线程池的通常策略是杀死least recently used 线程,通常这意味着产生一个新线程将确保预先退出的线程是被杀死的线程。

诚然,我没有找到任何资源来支持 nginx 的池收集策略是 LRU 的说法,但它并非不可能,在这种情况下,保持连接处于活动状态并不会节省太多。

【讨论】:

    【解决方案2】:

    几年后我问这个问题,我似乎找到了答案。

    (gdb) bt
    #0  close () at ../sysdeps/unix/syscall-template.S:84
    #1  0x0000000000a40dff in fcgi_close (req=0x1dae3c0, force=0, destroy=1) at /home/dinosaur/Downloads/php-7.2.2/main/fastcgi.c:1311
    #2  0x0000000000a41a0d in fcgi_finish_request (req=0x1dae3c0, force_close=0) at /home/dinosaur/Downloads/php-7.2.2/main/fastcgi.c:1670
    #3  0x0000000000a4d3b3 in sapi_cgi_deactivate () at /home/dinosaur/Downloads/php-7.2.2/sapi/fpm/fpm/fpm_main.c:828
    #4  0x00000000008bcf35 in sapi_deactivate () at /home/dinosaur/Downloads/php-7.2.2/main/SAPI.c:532
    #5  0x00000000008afa0e in php_request_shutdown (dummy=0x0) at /home/dinosaur/Downloads/php-7.2.2/main/main.c:1913
    #6  0x0000000000a50614 in main (argc=1, argv=0x7ffc8b6936e8) at /home/dinosaur/Downloads/php-7.2.2/sapi/fpm/fpm/fpm_main.c:1994
    

    当php-fpm启动时,init之后,它会循环处理每一个请求

    while (fcgi_accept_request(request) >= 0) {
       ...
       php_execute_script(&file_handle);   // zend engine compile and run the opcode
       ...
       php_request_shutdown((void *) 0);  // close connection
    }
    

    fcgi_accept_request函数中,socket fd是4

    1411    req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len);
    (gdb) n
    1414    client_sa = sa;
    Breakpoint 6, fcgi_accept_request (req=0x1dae3c0) at /home/dinosaur/Downloads/php-7.2.2/main/fastcgi.c:1414
    1414    client_sa = sa;
    (gdb) p req->fd
    $18 = 4
    

    当关闭时,它关闭套接字 fd 4

    Breakpoint 4, fcgi_close (req=0x1dae3c0, force=0, destroy=1) at /home/dinosaur/Downloads/php-7.2.2/main/fastcgi.c:1272
    1272    {
    (gdb) p req->fd
    $19 = 4
    

    结论

    所以,我认为在 php7 中,请求完成时 fpm 关闭,所以它不是持久连接?

    【讨论】:

      猜你喜欢
      • 2014-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多