PHP高并发部署实录:香港CN2链路下每请求省0.4ms的Nginx/PHP-FPM内核级手术

先说结论:香港CN2是不错的链路,但多数人把高并发优化的目光全放在PHP-FPM进程数和MySQL慢查询上。本文基于轻云互联香港CN2服务器实操验证,直击网络栈、TLS握手、Unix Socket隔离层三个订单系统压测中发现的隐藏瓶颈,不扯概念,全部命令化。 ## 1. 第一刀:砍向延迟的“双向RTT放大器” CN2链路的特点是延迟低至4-8ms,但丢包率往往不为零。TCP拥塞控制算法默认的 `cubic` 在丢包恢复时会线性增加拥塞窗口,在跨国链路上会放大抖动。 查看当前算法: ```bash sysctl net.ipv4.tcp_congestion_control ``` 实测在CN2链路下,改为 `bbr` 并调整 `tcp_notsent_lowat`(降低发送缓冲区低水位标记,让Nginx更快感知可写事件): ```bash cat >> /etc/sysctl.conf <<'EOF' net.ipv4.tcp_congestion_control = bbr net.ipv4.tcp_notsent_lowat = 16384 net.ipv4.tcp_mtu_probing = 1 net.ipv4.tcp_slow_start_after_idle = 0 EOF sysctl -p ``` `tcp_mtu_probing` 在CN2链路MTU黑洞场景下能自动降级。`tcp_slow_start_after_idle` 关闭空闲后慢启动,对长连接时段的突发请求是个明显的隐形收益,压测中P99延迟降低了0.4ms。 ## 2. 第二刀:PHP-FPM的socket隔离 多数人用的是默认的 `/var/run/php-fpm/www.sock`,所有站点共用。在https下,PHP进程池会因不同应用的空闲状态互相“吵闹”(比如一个站点慢查询导致worker被占满,另一个站点的健康请求排队)。 结合Nginx的 `fastcgi_pass unix:/run/php-fpm-xxx.sock`,按核心业务和边缘业务拆分PHP-FPM池,并用 `cgroup` 限制IO: ```bash mkdir -p /sys/fs/cgroup/blkio/php-io echo "253:0 1048576" > /sys/fs/cgroup/blkio/php-io/blkio.throttle.read_bps_device echo "253:0 1048576" > /sys/fs/cgroup/blkio/php-io/blkio.throttle.write_bps_device ``` 在 `/etc/php-fpm.d/order.conf` 池配置中绑定worker数和request_terminate_timeout,而核心池 `/etc/php-fpm.d/core.conf` 使用短超时+高worker数: ```ini [core-pool] listen = /run/php-fpm-core.sock listen.backlog = 4096 pm = dynamic pm.max_children = 80 pm.start_servers = 20 pm.min_spare_servers = 10 pm.max_spare_servers = 40 pm.max_requests = 10000 request_terminate_timeout = 10s ``` 关键是 `listen.backlog`。CN2链路到来访请求极快,TCP accept队列如果太短会直接SYN丢弃。 ## 3. Nginx keepalive + fastcgi_finish_request的取舍 很多人不敢用 `fastcgi_finish_request`,怕连接被提前关闭。实际上在Nginx + PHP-FPM下,这个函数可以让PHP提前返回结果给Nginx,后续的耗时操作(如写日志)不占用worker。 但注意坑点:Nginx收到响应后如果未配置 `fastcgi_keep_conn on`,它会关闭到PHP-FPM的socket连接,那么PHP进程内还没执行完的 `fastcgi_finish_request` 后面代码,如果尝试向客户端输出或操作header会报错。 部署时建议在 `nginx.conf` 的 `http` 段中明确: ```nginx fastcgi_keep_conn on; upstream php_backend { server unix:/run/php-fpm-core.sock; keepalive 32; } ``` 这里 `keepalive 32` 指向Unix Socket,要配合PHP-FPM 7.4+。实测在轻云互联香港CN2线路 + 4核8G机型上,这种配置让接口的TCP连接复用率提升了近3倍,CPU占用率下降了12%。 ## 4. session落盘与Redis并存的高并发陷阱 PHP高并发下,默认的filesession会卡在磁盘IO上,尤其是在NFS或云硬盘上。但直接全都切Redis又会导致Redis故障时全站不可用。 较稳妥的折中方案是`session.save_handler`先用Redis,同时在Redis连接失败时自动降级为memcached再降级到文件: ```php