我们来看一段Nginx中fastcgi_pass的配置:

  1. location ~ .php$ {
  2. root /home/wwwroot;
  3. fastcgi\_pass 127.0.0.1:9000;
  4. #fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
  5. #fastcgi_pass unix:/tmp/php-cgi.sock;
  6. try_files $uri /index.php =404;
  7. fastcgi_split_path_info ^(.+\.php)(/.+)$;
  8. fastcgi_index index.php;
  9. fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  10. include fastcgi_params;
  11. }

两种方式

Nginx和PHP-FPM的进程间通信有两种方式,一种是TCP,一种是UNIX Domain Socket.

1、tcp

允许通过网络进程之间的通信,也可以通过loopback进行本地进程之间通信。

2、UNIX Domain Socket

允许在本地运行的进程之间进行通信。
其中TCP是IP加端口,可以跨服务器。
而UNIX Domain Socket不经过网络,只能用于Nginx跟PHP-FPM都在同一服务器的场景。用哪种取决于你的PHP-FPM配置:

方式1:
php-fpm.conf: listen = 127.0.0.1:9000
nginx.conf: fastcgi_pass 127.0.0.1:9000;
方式2:
php-fpm.conf: listen = /tmp/php-fpm.sock
nginx.conf: fastcgi_pass unix:/tmp/php-fpm.sock;

其中php-fpm.sock是一个文件,由php-fpm生成,类型是srw-rw—-.

3、UNIX Domain Socket和tcp链接的区别

一方面:

UNIX Domain Socket可用于两个没有亲缘关系的进程,是目前广泛使用的IPC机制。
UNIX Domain Socket减少了不必要的tcp开销,而tcp需要经过loopback,还要申请临时端口和tcp相关资源。

另一方面:

unix socket高并发时候不稳定,连接数爆发时,会产生大量的长时缓存,在没有面向连接协议的支撑下,大数据包可能会直接出错不返回异常。
tcp这样的面向连接的协议,多少可以保证通信的正确性和完整性

UNIX Domain Socket(只能是本地):
Nginx <=> socket <=> PHP-FPM
TCP Socket(本地回环):
Nginx <=> socket <=> TCP/IP <=> socket <=> PHP-FPM
TCP Socket(Nginx和PHP-FPM位于不同服务器):
Nginx <=> socket <=> TCP/IP <=> 物理层 <=> 路由器 <=> 物理层 <=> TCP/IP <=> socket <=> PHP-FPM

4、类似的软件

像mysql命令行客户端连接mysqld服务也类似有这两种方式:
使用Unix Socket连接(默认):

mysql -uroot -p --protocol=socket --socket=/tmp/mysql.sock

使用TCP连接:

mysql -uroot -p --protocol=tcp --host=127.0.0.1 --port=3306

5、总结

此处,用unix domain socker的方式,比tcp方式速度更快,但是tcp是面向连接的协议,稳定性更高,这是一个区别点。

6、进一步优化

提高nginx和php-fpm使用的 unix socket稳定性(单机能力有限)

1.修改内核参数

net.unix.max_dgram_qlen = 4096
net.core.netdev_max_backlog = 4096
net.core.somaxconn = 4096

2.提高backlog

backlog默认位128,1024这个值最好换算成自己正常的QPS。

nginx.conf
server{
  listen 80 default backlog=1024;
}
php-fpm.conf
listen.backlog = 1024

3.增加sock文件和php-fpm实例

在/dev/shm新建一个sock文件,在nginx中通过upstream魔抗将请求负载均衡到两个sock文件,
并且将两个sock文件分别对应到两套php-fpm实例上。