曾经有一个面试官,问我有没有在原公司做过什么创新的东西,我当时懵了,的确想不出来,
因为在公司的两年一直在学习,还没有到厚积薄发。但是事后一想,有一点的确能算的上,
虽然不是我发明的,但公司其他同事的确没人想到或注意过。我在离职前一段时间,跟架构师
提过,叫他们换一下使用这种方式,不过到底有没有去做了,我也不知道。不过,那个问题
问的真的很好,能直接知道来面的这个人是不是泛泛之辈。
我提的就是用unix socket来代替tcp socket进行nginx,php之间的数据传输,当然大牛们
应该老早明了这个做法了。我是在看了APUE之后才更加理解他们差别的,当然FREEBSD上也有
大牛在讨论,结果都是一致的。因为tcp 四层协议并不只是逻辑上存在的,在操作系统内核里
都有它们对应的C代码的,那么一次请求,相当于nginx这边是四层从上往下走,
然后到php进程那边,四层协议从下往上走,然后php执行完脚本产生html,
把数据再在四层里从上往下走输送到nginx这边,而等在这边的nginx进程把那些数据又从下往上走,
然后经过一系列处理,再在四层协议里去走一遍,这次是经过eth0接口返回浏览器了。
单次请求,相当于单单nginx,php之间,那四层协议的代码都走了4次。如果高并发时,
亿级请求时呢,要消耗多少内存和cpu和时间拖延阿?如果用unix socket,
当然没有那4层协议的C代码了,虽然说也是要用到系统调用的,socket,bind,send,recv
这些函数接口都一样,但底层实现不一样。
简而言之,unix socket 就是buffer与bufer之间数据交换。而一般的大型网站,
都可以用unix socket 的,除非 nginx 进程,php进程不在同一台机器上,

配置
nginx通过unix socket和fastcgi通信,比tcp socket要高效,重负荷下可以考虑。
1、在nginx.conf中修改配置为:

  1. fastcgi_pass unix:/tmp/php-cgi.sock;
  2. #fastcgi_pass 127.0.0.1:9000;

2、在php-fpm.conf中修改配置为:

  1. <value name="listen_address">/tmp/php-cgi.sock</value>

所以就有以下问题:
在配置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. }

主要是关于fastcgi_pass参数,

  1. #fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
  2. #fastcgi_pass unix:/tmp/php-cgi.sock;

这两种方式有什么区别,php7该用哪一个?
答案如下:
Nginx和PHP-FPM的进程间通信有两种方式,一种是TCP,一种是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——.

UNIX Domain Socket可用于两个没有亲缘关系的进程,是目前广泛使用的IPC机制,比如X Window服务器和GUI程序之间就是通过UNIX Domain Socket通讯的.这种通信方式是发生在系统内核里而不会在网络里传播.UNIX Domain Socket和长连接都能避免频繁创建TCP短连接而导致TIME_WAIT连接过多的问题.对于进程间通讯的两个程序,UNIX Domain Socket的流程不会走到TCP那层,直接以文件形式,以stream socket通讯.如果是TCP Socket,则需要走到IP层,对于非同一台服务器上,TCP Socket走的就更多了.

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

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

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

使用TCP连接:

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

php-cgi.sockphp-fpm.sock该用哪个呢?

名字随便起,只要对上php-fpm.conf里定义的名字就行.

分类: web

标签:   nginx