随着php脚本语言使用的普及,目前webserice服务大部分都在用nginx+(php-fpm)的结构,了解了其工作过程后才可以在各个方面想办法做调整优化和故障排查,从以下几点总结一下这种模型。

一、nginx和php-fpm的关系和分工

nginx是web服务器,php-fpm是一个PHPFastCGI进程管理器,两者遵循fastcgi的协议进行通信,nginx负责静态类似html文件的处理,php-fpm负责php脚本语言的执行,这么设计的目的是为了解耦前端nginx和后端的php,不至于让容易出问题的php脚本堵塞整个nginx的业务处理,影响用户体验,因为php脚本语言的执行是会比较容易出问题的。nginx之所以能处理成千上万高并发业务,除其本身的异步非阻塞模式,在与和其他模块的耦合扩展方法也是分不开的,在nginx的设计里不能接受的就是阻塞,不过并非完全没有梗,比如说用到的最多的多进程单线程的模式,由于nginx日志没有单独的处理进程,如果收集日志时处理不当就会把worker进程堵死。

对应nginx+php-fpm的模型结构图如下:


1、nginx的工作简介(对应上图看)

在接到php的脚本请求后,nginx通过fastcgi_pass指令将请求传递给后端php-fpm的worker进程处理,在此过程中,nginx做了各种超时机制、缓存机制、buffer机制和长连接机制等来保障与后端的php-fpm能够良性高效的合作。

在超时机制方面控制nginx对后端php的等待时间,通过各种timeout指令进行控制,例如:

1
2
3
fastcgi_connect_timeout   后端链接时间
fastcgi_send_timeout    数据发送时间,两次成功发送时间差,不是整个发送时间
fastcgi_read_timeout    数据接收时间,两次成功接收时间差,不是整个接收时间

当超时后会返回504超时的状态码,在buffer机制指令也有很多,例如:

1
2
fastcgi_buffer_size 存放fastcgi传过来的响应头,一般设置为分页大小
fastcgi_buffers 存放fastcgi传过来的相应内容,一般设置分页的倍数,格式例如 8  4k|8k

另外还有一些其它的缓存、长连接机制不做介绍,当设置不合理时也会出现5XX错误,nginx的文章介绍写了有很多的,不再做过多的说明。

2、php-fpm工作介绍(对应上图看)

Php-fpm是一个PHPfastcgi进程管理器,在启动后会有master和worker两种进程,master负责接收外部信号和管理worker进程,worker进程是负责干活的,处理nginx传过来的任务。

master进程只有一个,负责监听端口和管理worker进程,每次传来任务,与前端的nginx建立3次握手后放入连接队列,供worker进程进行accept,当worker进程出现错误或执行超时时,负责将worker进程重启或者杀掉,是php-fpm模型中的大内总管。

Worker进程是工作进程,每个worker进程都独立的执行php程序脚本,然后把执行的结果通过fastcgi协议交给nginx,执行过程中受master的管理。在工作中,worker进程去竞争accept管理进程master的链接队列,accept函数将从连接请求队列中获得连接信息,创建新的socket,并返回该套接字的fd,新创建的socket用于服务器与nginx的通信,而原来的套接字仍然处于监听状态。

php-fpm可以配置多个pool,所有pool由master统一管理监听不同端口并分配不同worker进程池,worker进程池支持动态prefork同时也支持静态开启,服务器内存较大时建议直接计算后配置静态资源池,可以减少频繁prefork进程所带来的开销,提高服务质量,由于进程模型越跑程序耗费越大,因为每个worker进程可以配置执行多少个请求后进行重启,对应的池子的指令和执行多少个请求的指令如下:

1
2
3
pm = static | dynamic | ondemand 静态池、服务优先、内存优先
pm.max_children = 256  开启的最大php进程数
pm.max_requests = 1024   在执行了1024个请求后重启worker进程

这也是我们线上服务器的配置,我们线上用的web服务的机器是12核cpu、12G内存,nginx开启12个worker进程,php开启256个进程,跑起来后每个进程大概占用30M内存,也就是(256+12)*30=8G ,另外还跑了一些配管、监控、统计、日志收集等七七八八的软件,整体业务是比较轻松的,这种静态池的配置大大减少了prefork进程带来的开销,RT时间100ms以内的占到90%以上(这个与程序写的如何有关),运行一段时间后的开销截图如下:

二、此模型结构常见的5XX服务器端错误及优化(对应图1看)

1、nginx日志里产生502错误

第一种情况,php-fpm的worker进程执行php程序脚本时,超过了配置的最长执行时间,master进程将worker进程杀掉,直接返回502。

返回502后nginx对应的error日志是104: Connection reset by peer

对应的php执行时间的配置如下,一些版本中php-fpm的配置会覆盖php.ini的配置,使php.ini的配置不起作用:

1
2
php.ini中默认30s:max_execution_time =
php-fpm中:request_terminate_timeout =

第二种情况,连接请求数(accpet之前)超出了端口所能监听的tcp连接的最大值(backlog的值),进不了fpm等待accept的链接队列,直接返回502,这里可能会产生tcp重传;

返回502后nginx对应的error日志是111: Connection refused

backlog的值是半连接和全连接的总和,他的存在也有短时间缓冲解耦nginx请求与fpm处理的作用,半连接指收到了syn请求,3次握手尚未建
立,全连接指的是3次握手已经成功,不过尚未被accpet的请求,fpm里面有调节的参数,如果fpm的参数设置为-1,则默认走的是系统内核参数
net.core.somaxconn的设置值,如果不设置可以在/proc/sys/net/core/somaxconn里查看,默认值是128,所
以在连接请求较高的业务里要增大这个值。

第三种情况,网络卡时,客户端断开连接,nginx处显示499,然后php检查到前端nginx产生abort后,又master结束此条任务的继而产生502,一般此种情况的报警,先是499,过会儿变成502,再过一会变成504.

减少避免502报错优化建议:

502主要从php-fpm的配置方考虑,根据服务器情况,适量增大php-fpm的工作进程数,适当增加php的执行时间,适当增加backlog值。

php
的工作进程数也不是越大越好,这种进程模型运行时间长了占的内存会增大,一般一个php进程是占到30M左右的内存,开多少合适自己算吧,nginx的
worker进程一般也能跑到30M的内存,综合计算一下;php的执行时间可以根据你的服务标准来设定,超过服务时间浏览器返回的是502错误,这个按
照实际的情况处理吧,一般情况要设置超时时间,避免某些请求慢,将整个业务堵死;至于backlog值,当程序写的比较好时,建议设置其数量为php工作
进程的1到2倍。

2、nginx日志里产生504错误

第一种情况,php的worker进程池处理慢,无法尽快处理等待accept的链接队列,导致3次握手后的链接队列长时间没有被accept,nginx链接等待超时;

返回504后nginx对应的error日志是110: Connection timed out

第二种情况,后端php-fpm执行脚本的时间太长,超过了nginx配置的超时机制,这个时候也是会报出504错误的。

第三种情况,客户端的网络及其差,php将请求处理完交给nginx后,nginx没能在超时时间内将内容全部吐给用户,这时也会超时,只有504而没有502。

减少避免504报错的优化建议:

504主要从nginx的配置方考虑,根据业务情况配置好超时的各种机制,包含但不限于下属参数:

1
2
3
4
fastcgi_connect_timeout
fastcgi_send_timeout 
fastcgi_read_timeout 
。。。。。。。。

另外:
配置过程中,比如遇到大并发或者是特殊业务的场景,不合理的fd、buffer等设置也会带来5XX错误,比如说大并发连接的业务要增大系统和单个程序的
fd数量,如果是上传业务要增大头buffer等,这些要视情况而做优化,正所谓道法自然,术变万千,要以不变应万变。

WebService之nginx+(php-fpm)结构模型剖析及优化的更多相关文章

  1. nginx+php-fpm结构模型剖析及优化(转载)

    一.nginx和php-fpm的关系和分工 nginx是web服务器,php-fpm是一个PHPFastCGI进程管理器,两者遵循fastcgi的协议进行通信,nginx负责静态类似html文件的处理 ...

  2. 记录一次自己对nginx+fastcgi(fpm)+mysql压力测试结果

    nginx + fastcgi(fpm) 压力测试: CentOS release 5.9 16核12G内存 静态页面: 并发1000,压测200秒,测试结果: 系统最大负载5.47 成功响应: 25 ...

  3. 深入理解PHP之:Nginx 与 FPM 的工作机制

    网络上有很多关于如何配置 Nginx + FPM 的文章,但它们更多从操作的角度出发,告诉我们怎么做,但却没有告诉我们为什么要这么做,本文从 Nginx 与 FPM 的工作机制出发,探讨配置背后的原理 ...

  4. Nginx突破高并发的性能优化 - 运维笔记

    在日常的运维工作中,经常会用到nginx服务,也时常会碰到nginx因高并发导致的性能瓶颈问题.今天这里简单梳理下nginx性能优化的配置(仅仅依据本人的实战经验而述,如有不妥,敬请指出~) 一.这里 ...

  5. [Nginx] - PHP+FPM相关的配置

    CodeIgniter的配置: worker_processes ; events { worker_connections ; } http { include mime.types; defaul ...

  6. zabbix自定义key监控nginx和fpm(网站并发数)

    一. nginx编译参数 监控nginx,主要讲解监控并发数 --prefix=/usr/local/nginx --with-http_stub_status_module zabbix编译参数的查 ...

  7. nginx和fpm的进程数配置和502,504错误

    502 和 php-fpm.conf 1.php-cgi进程数不够用.php执行时间长,导致没有空闲进程处理新请求. 2.php-cgi进程死掉.php-fpm超时时间短,当前进程执行超时关闭连接. ...

  8. Nginx PHP fpm forbidden 原因

    可能是标红目录层级不一致 location / { root /var/www/html/public; index index.php; } location ~ \.php$ { root /va ...

  9. 对FPM 模块进行参数优化!

    Nginx 的 PHP 解析功能实现如果是交由 FPM 处理的,为了提高 PHP 的处理速度,可对FPM 模块进行参数跳转.FPM 优化参数:pm 使用哪种方式启动 fpm 进程,可以说 static ...

随机推荐

  1. 支持开源,推动Orchard

    希望正在研究果园,和对果园感兴趣的,加入Orchard高级开发群,进行交流和讨论及深入研究Orchard开发,我们致力寻求志同道合推动Orchard发展的屌丝!!! 干净.专注.社区力量的圈子

  2. blfs(systemd版本)学习笔记-wget的安装与配置

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! blfs wget项目地址:http://www.linuxfromscratch.org/blfs/view/stable-s ...

  3. python学习之解决中英文混合输出的排版问题

    在python的格式输出时常使用format()方法,其中的多余空间默认使用英文空格作为占位符,不方便中英混合时的格式输出,因此我们要为其中的中文字符串使用占字符较大的中文空格符作为多余空间的占位符. ...

  4. 2017-12-26 Java关键字的汉化用词探讨

    @狗屎咖啡 的为GCC添加中文关键字项目对C关键词进行了汉化. 风格比较简约, 如'if'-如, 'else'-另. 个人感觉在中文编程语言尚未成熟之时, 不妨集思广益, 首先列出一些可选项, 然后从 ...

  5. OneMap Client API

    MapSystem.Map.SmMap类 方法 mergerGeo:function(geoList) 将多个几何图形合并(支持面.线),组合成一个复合对象 例子: var geo=this.myMa ...

  6. git 查看/修改用户名、密码

    用户名和邮箱地址的作用 用户名和邮箱地址是本地git客户端的一个变量,不随git库而改变. 每次commit都会用用户名和邮箱纪录. github的contributions统计就是按邮箱来统计的. ...

  7. Python 基于python操纵redis入门介绍

    基于python操纵redis入门介绍 by:授客  QQ:1033553122 测试环境 redis-3.0.7 CentOS 6.5-x86_64 python 3.3.2 基于Python操作R ...

  8. Oracle 关闭数据库(未使用Oracle Restart)

    Oracle关闭数据库(未使用Oracle Restart) by:授客 QQ:1033553122 SHUTDOWN [选项] 选项说明: NORMAL-语句执行后,不允许创建新的连接:等待所有当前 ...

  9. Java数据解析---SAX

    一.Sax解析 是从头到尾逐行逐个元素读取内容,修改较为不便,但适用于只读的大文档. Sax采用事件驱动的方式解析文档.简单点说,如同在电影院看电影一样,从头到尾看一遍就完了,不能回退(Dom可来来回 ...

  10. spring 使用外部属性文件

    一.PropertyPlaceholderConfigurer spring提供的PropertyPlaceholderConfigurer实现类能够使Bean在配置时引用外部属性文件. Proper ...