PHP-FPM和Nginx的通信机制详解


Posted in PHP onFebruary 01, 2019

PHP-FPM 介绍

CGI 协议与 FastCGI 协议

每种动态语言( PHP,Python 等)的代码文件需要通过对应的解析器才能被服务器识别,而 CGI 协议就是用来使解释器与服务器可以互相通信。PHP 文件在服务器上的解析需要用到 PHP 解释器,再加上对应的 CGI 协议,从而使服务器可以解析到 PHP 文件。

由于 CGI 的机制是每处理一个请求需要 fork 一个 CGI 进程,请求结束再kill掉这个进程,在实际应用上比较浪费资源,于是就出现了CGI 的改良版本 FastCGI,FastCGI 在请求处理完后,不会 kill 掉进程,而是继续处理多个请求,这样就大大提高了效率。

PHP-FPM 是什么

PHP-FPM 即 PHP-FastCGI Process Manager, 它是 FastCGI 的实现,并提供了进程管理的功能。进程包含 master 进程和 worker 进程两种;master 进程只有一个,负责监听端口,接收来自服务器的请求,而 worker 进程则一般有多个(具体数量根据实际需要进行配置),每个进程内部都会嵌入一个 PHP 解释器,是代码真正执行的地方。

Nginx 与 php-fpm 通信机制

当我们访问一个网站(如 www.test.com)的时候,处理流程是这样的:

  www.test.com
        |
        |
      Nginx
        |
        |
路由到 www.test.com/index.php
        |
        |
加载 nginx 的 fast-cgi 模块
        |
        |
fast-cgi 监听 127.0.0.1:9000 地址
        |
        |
www.test.com/index.php 请求到达 127.0.0.1:9000
        |
        |
     等待处理...

Nginx 与 php-fpm 的结合

在 Linux 上,nginx 与 php-fpm 的通信有 tcp socket 和 unix socket 两种方式。

tcp socket 的优点是可以跨服务器,当 nginx 和 php-fpm 不在同一台机器上时,只能使用这种方式。

Unix socket 又叫 IPC(inter-process communication 进程间通信) socket,用于实现同一主机上的进程间通信,这种方式需要在 nginx配置文件中填写 php-fpm 的 socket 文件位置。

两种方式的数据传输过程如下图所示:

PHP-FPM和Nginx的通信机制详解

二者的不同:

由于 Unix socket 不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。所以其效率比 tcp socket 的方式要高,可减少不必要的 tcp 开销。不过,unix socket 高并发时不稳定,连接数爆发时,会产生大量的长时缓存,在没有面向连接协议的支撑下,大数据包可能会直接出错不返回异常。而 tcp 这样的面向连接的协议,可以更好的保证通信的正确性和完整性。

Nginx 与 php-fpm 结合只需要在各自的配置文件中做设置即可:

1) Nginx 中的配置

以 tcp socket通信为例

server {
 listen  80; #监听 80 端口,接收http请求
 server_name www.test.com; #就是网站地址
 root /usr/local/etc/nginx/www/huxintong_admin; # 准备存放代码工程的路径
 #路由到网站根目录 www.test.com 时候的处理
 location / {
  index index.php; #跳转到 www.test.com/index.php
  autoindex on;
 } 

 #当请求网站下 php 文件的时候,反向代理到 php-fpm
 location ~ \.php$ {
  include /usr/local/etc/nginx/fastcgi.conf; #加载 nginx 的 fastcgi 模块
  fastcgi_intercept_errors on;
  fastcgi_pass 127.0.0.1:9000; # tcp 方式,php-fpm 监听的 IP 地址和端口
  # fasrcgi_pass /usr/run/php-fpm.sock # unix socket 连接方式
 }

}

2) php-fpm 的配置

listen = 127.0.0.1:9000
# 或者下面这样
listen = /var/run/php-fpm.sock

注意,在使用 unix socket 方式连接时,由于 socket 文件本质上是一个文件,存在权限控制的问题,所以需要注意 nginx 进程的权限与 php-fpm 的权限问题,不然会提示无权限访问。(在各自的配置文件里设置用户)

通过以上配置即可完成 php-fpm 与 nginx 的通信。

在应用中的选择

如果是在同一台服务器上运行的 nginx 和 php-fpm,且并发量不高(不超过1000),选择unix socket,以提高 nginx 和 php-fpm 的通信效率。

如果是面临高并发业务,则考虑选择使用更可靠的 tcp socket,以负载均衡、内核优化等运维手段维持效率。

若并发较高但仍想用 unix socket 时,可通过以下方式提高 unix socket 的稳定性。

1)将sock文件放在 /dev/shm 目录下,此目录下将 sock 文件放在内存里面,内存的读写更快。

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 实例上。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
一个php作的文本留言本的例子(一)
Oct 09 PHP
php is_file()和is_dir()用于遍历目录时用法注意事项
Mar 02 PHP
php操作JSON格式数据的实现代码
Dec 24 PHP
php页面消耗内存过大的处理办法
Mar 18 PHP
php中静态类与静态变量用法的区别分析
Jan 15 PHP
PHP使用gmdate实现将一个UNIX 时间格式化成GMT文本的方法
Mar 19 PHP
PHP测试成功的邮件发送案例
Oct 26 PHP
分享五个PHP7性能优化提升技巧
Dec 07 PHP
thinkPHP简单遍历数组方法分析
May 16 PHP
php微信分享到朋友圈、QQ、朋友、微博
Feb 18 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
Mar 29 PHP
PHP+Redis事务解决高并发下商品超卖问题(推荐)
Aug 03 PHP
Laravel框架自定义验证过程实例分析
Feb 01 #PHP
thinkPHP框架RBAC实现原理分析
Feb 01 #PHP
PHP PDOStatement::fetchColumn讲解
Jan 31 #PHP
PHP PDOStatement::fetchAll讲解
Jan 31 #PHP
PHP PDOStatement::fetch讲解
Jan 31 #PHP
PHP PDOStatement::execute讲解
Jan 31 #PHP
PHP PDOStatement::errorInfo讲解
Jan 31 #PHP
You might like
php 数组动态添加实现代码(最土团购系统的价格排序)
2011/12/30 PHP
php图片加中文水印实现代码分享
2012/10/31 PHP
微信公众平台网页授权获取用户基本信息中授权回调域名设置的变动
2014/10/21 PHP
浅析PHP7新功能及语法变化总结
2016/06/17 PHP
PHP实现的用户注册表单验证功能简单示例
2019/02/25 PHP
js中cookie的使用详细分析
2008/05/28 Javascript
Jquery 表单取值赋值的一些基本操作
2009/10/11 Javascript
JavaScript 加号(+)运算符号
2009/12/06 Javascript
网络图片延迟加载实现代码 超越jquery控件
2010/03/27 Javascript
JavaScript获得url所有参数键值表的方法
2015/03/21 Javascript
JavaScript给按钮绑定点击事件(onclick)的方法
2015/04/07 Javascript
JavaScript手机振动API
2016/06/11 Javascript
JavaScript实现水平进度条拖拽效果
2017/01/18 Javascript
Angularjs Ng_repeat中实现复选框选中并显示不同的样式方法
2018/09/12 Javascript
vue中的mvvm模式讲解
2019/01/31 Javascript
Vue实现页面添加水印功能
2019/11/09 Javascript
Vue filter 过滤当前时间 实现实时更新效果
2019/12/20 Javascript
[00:33]DOTA2上海特级锦标赛 CDEC战队宣传片
2016/03/04 DOTA
[02:36]DOTA2上海特锦赛 回忆电竞生涯的重要瞬间
2016/03/25 DOTA
Python网络编程 Python套接字编程
2017/09/13 Python
Python找出最小的K个数实例代码
2018/01/04 Python
Python global全局变量函数详解
2018/09/18 Python
selenium + python 获取table数据的示例讲解
2018/10/13 Python
Python把对应格式的csv文件转换成字典类型存储脚本的方法
2019/02/12 Python
Django实现内容缓存实例方法
2020/06/30 Python
Python中使用aiohttp模拟服务器出现错误问题及解决方法
2020/10/31 Python
HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题
2021/01/19 HTML / CSS
荷兰的时尚市场:To Be Dressed
2019/05/06 全球购物
三年级语文教学反思
2014/02/01 职场文书
感恩教育活动总结
2014/05/05 职场文书
入职担保书范文
2014/05/21 职场文书
离婚协议书范本
2015/01/26 职场文书
小学感恩主题班会
2015/08/12 职场文书
《自己的花是让别人看的》教学反思
2016/02/19 职场文书
Redis实现订单自动过期功能的示例代码
2021/05/08 Redis
手写实现JS中的new
2021/11/07 Javascript