PHP-FPM 性能配置优化

4 核 8 G 服务器大约可以开启 500 个 PHP-FPM,极限吞吐量在 580 qps (Query Per Second 每秒查询数)左右。

Nginx + php-fpm 是怎么工作的?

php-fpm 全称是 PHP FastCGI Process Manager 的简称,从名字可得知,是一个 FastCGI 的管理器。

什么是 FastCGI?

FastCGI 是 Fast Common Gateway Interface 的简称,是一种交互程序(此处是 PHP)与 Web 服务器之间的 通信协议。FastCGI 是早期通用网关接口(CGI)的增强版本。

注意 FastCGI 和 CGI 都是一种 通信协议,独立于任何语言。Web 服务器无须对语言有任何了解。除 PHP 有 php-fpm 外,像 Python, Ruby, Perl, Tcl, C/C++, 和 Visual Basic 都有其各自的 CGI 和 FastCGI 实现。

CGI 和 FastCGI 的区别?

CGI 程序运行在独立的进程中,并对每个 Web 请求创建一个进程,这种方法非常容易实现,但效率很差,难以扩展。 面对大量请求,进程的大量创建和消亡使操作系统性能大大下降。 此外,由于地址空间无法共享,也限制了资源重用。

FastCGI 致力于减少网页服务器与 CGI 程序之间交互的开销,从而使服务器可以同时处理更多的网页请求。与为每个请求创建一个新的进程不同,FastCGI 使用持续的进程来处理一连串的请求。这些进程由 FastCGI 服务器管理(FPM),而不是 Web 服务器。当进来一个请求时,Web 服务器把环境变量和这个页面请求通过一个 Socket 或者 TCP Connection 传递给 FastCGI 进程:

nginx + php-fpm 工作模式

php-fpm 进程数调优

fpm 服务启动初始化时,会根据配置信息里设置的运行模式,来选择是否创建、以及创建多少 CGI 进程,这些进程随时待命,等待处理从 Web 服务器传送过来的请求:

nginx 配合 php-cgi 的运行

PHP 7.2 FPM 进程池的配置信息位于:

/etc/php/7.2/fpm/pool.d/www.conf

搜寻下 pm 运行模式的配置,默认是 dynamic :

pm = dynamic

fpm 的运行模式有三种:

  • ondemand 按需创建
  • dynamic 动态创建
  • static 固定数量

ondemand

ondemand 初始化时不会创建待命的进程。并且会在空闲时将进程销毁,请求进来时再开启。一般是在共享的 VPS 上使用。是一种比较 节省内存 的 FPM 运行方式,不过因为其频繁创建和销毁进程,性能表现不佳。

相关参数:


; 默认是 10 秒,超过 10 秒即销毁
pm.process_idle_timeout = 10s;; 最大并存进程数,超过此值将不再创建
pm.max_children = 50; 每个进程最多处理多少个请求,超过此值将自动销毁
pm.max_requests = 1000

dynamic

动态创建,这个是默认选项,也是比较灵活的选项。兼顾稳定和快速响应。同时有四个参数会影响此配置:


; FPM 启动时创建的进程数
pm.start_servers = 10; 最大并存进程数,超过此值将不再创建
pm.max_children = 50; 空闲进程数最小值,如果空闲进程小于此值,则创建新的子进程
pm.min_spare_servers = 10; 空闲进程数最大值,如果空闲进程大于此值,则进行清理
pm.max_spare_servers = 40; 每个进程最多处理多少个请求,超过此值将自动销毁
pm.max_requests = 1000

上面的注释已经很释义,空闲进程的概念需要讲下。按照上面的设置,fpm 启动时会有 10 个进程启动,此时这 10 个进程都属于「空闲进程」,随时待命。

进来了一个请求,一个进程前往处理,此时剩下 9 个「空闲进程」,fpm 发现少于 min_spare_servers 设置的值 10 ,就会新建一个进程作为「空闲进程」,此时系统存在 11 个进程,还是 10 个空闲进程。

在第一个请求还未处理完成时,突然一波流量进来,一口气进来了 50 个请求,因为 max_children 设置了 50 个封顶,所以 FPM 会新建 39 个进程,加上 10 个进行进程一起处理这波请求,此时系统中总共 50 个进程共存,50 个进程都属于繁忙中,未分配到进程的请求会等待着。

等所有的请求处理完成后,系统中共存的 50 个进程变成「空闲进程」,超过了 max_spare_servers 值 40 个的限制,超出的 10 个会被销毁,系统此时存在 40 个「空闲进程」,随时待命。

因为一直保证有「空闲进程」可供使用,所以 dynamic 的配置,相比 ondemand 进程要同时创建,响应速度还是比较快的。然而在还是避免不了频繁创建和销毁进程对系统造成的消耗。

static

固定进程数量是性能最好,资源利用率最高的运行方式,一般在要求单机性能最高的时候使用,例如你准备创建 PHP 服务器集群,希望每台机器都能物尽其用。

相关配置:


; FPM 启动时创建的进程数,并且会一直保持这个数
pm.max_children = 50; 每个进程最多处理多少个请求,超过此值将自动销毁
pm.max_requests = 1000

pm.max_children 的设置,需要我们每一个进程运行我们的程序,需要消耗多少内存,以及机器上有多少内存可供使用。

计算公式:


pm.max_children = 可用内存 / 每个进程暂用内存大小

注意可用内存不是本机所有内存,要除去其他程序运行,例如说你应该除去 Elasticsearch 占用了 2G 内存。

调试期间,要在生产环境中实战观察,一般建议使用 80% 的内存使用率,留 20% 给内存泄露的空间和其他软件运行。

最后是 pm.max_requests 值,需要我们观察应用是否有 内存泄漏。现代的 PHP 程序,尤其是 Laravel ,会依赖于非常多的扩展包,这些扩展包代码质量参差不齐,多少会出现内存泄漏的问题。如果内存泄露不严重,那么把值设置高一点,让单个进程在存活期间 多处理一些请求,如果内存泄露比较严重,应当酌情设置低一点。否则会出现系统 内存不够用,然后去使用 Swap 物理内存 的窘境。

修改后请记得重启 FPM:

sudo service php7.2-fpm restart

Unix Socket 和 TCP Socket

Nginx 连接 FPM 有 Unix Socket 和 TCP Socket 两种方式:

Unix Socket:


location ~ \.php$ {fastcgi_pass unix:/run/php/php7.2-fpm.sock
}

TCP Socket:


fastcgi_pass 127.0.0.1:9000;

如何选择?

Unix Socket 方式 比较快 而且 消耗资源少(差距不会太大 0.1% ~ 5% 的差别),但是缺点是只能本机使用,没有 TCP 灵活。

如果 Nginx 和 FPM 都在同一台服务器上,推荐使用 Unix Socket。如果是做 PHP 服务器集群,使用 Nginx 做负载均衡的话,只能采用 TCP 的链接方式。

如何设置成 TCP Socket 的连接方式?

以 PHP-FPM 7.2 为例:

/etc/php/7.2/fpm/pool.d/www.conf


listen = 127.0.0.1:9000

同时配置 Nginx 里的 fastcgi_pass 127.0.0.1:9000; ,并重启 FPM 和 Nginx:


sudo service php7.2-fpm restart
sudo service nginx restart

如何设置成 Unix Socket 的连接方式?

修改 FPM 进程池配置:

/etc/php/7.2/fpm/pool.d/www.conf


listen = /run/php/php7.2-fpm.sock

同时配置 Nginx 里的 fastcgi_pass unix:/run/php/php7.2-fpm.sock; ,并重启 FPM 和 Nginx:


sudo service php7.2-fpm restart
sudo service nginx restart

文件 /var/run/php/php7.2-fpm.sock 会在 FPM 启动时创建。

生产环境中一定要关闭掉 Xdebug 扩展

检查生产环境的 PHP 原生扩展文件夹里是否存在,以 PHP 7.2 为例存放路径为:

/etc/php/7.2/mods-available/xdebug.ini

找到以后确保使用 ; 符注释掉:

/etc/php/7.2/mods-available/xdebug.ini

;zend_extension=xdebug.so

重启 fpm


sudo service php7.2-fpm restart

检查 php-fpm 的进程数量

# 会多出两个进程数,是因为有一个不负责处理请求的 php-fpm master 进程和一个 grep 进程
ps -aux | grep php-fpm | wc -l

开启 Slow log 定位慢脚本

如何开启?

PHP-FPM 提供一个叫 慢日志 (slowlog) 的功能,来帮助我们定位执行慢的脚本。以 PHP 7.2 为例,FPM 的配置信息位于:

/etc/php/7.2/fpm/pool.d/www.conf

相关配置项:

; 慢日志的存储路径,默认 `$pool` 设置为 `www`
slowlog = /var/log/$pool.slow.log; 设置慢日志超时标准,设置为 0 代表关闭慢日志
request_slowlog_timeout = 1s; 慢日志记录脚本堆栈的深度
request_slowlog_trace_depth = 20

以上的配置翻译过来:指定 FPM 当发现有请求执行超过 1 秒钟的时候,将整个调用堆栈记录到 /var/log/www.slow.log 文件里,堆栈的深度不超过 20。

你可以把 1s 改成其他值,如 10s。有了以上的设置,裁剪图像尺寸的方法、 网络 I/O 相关的一些请求都经常出现在 PHP 慢日志中。你可以根据自己的情况来选择调整或者忽略。

如何分析?

可以使用 grep 命令来快速定位某个函数调用、或者脚本名称被记录的次数,记录的次数越多,优化的优先级就越高。以下是简单的 示例

grep -o 'fetch_github_user' /var/log/www.slow.log | wc -lgrep -o 'sendEmail' /var/log/www.slow.log | wc -l

需要注意的是,监控 Slowlog 和记录日志的过程会对 PHP 造成消耗, 切记 调试结束后,务必将其关闭。

开启 OPcache

OPcache 是由 PHP 官方公司 Zend 开发的一款免费使用的 PHP 优化加速拓展。他可以将 PHP 脚本编译后的 bytecode 缓存在共享内存中供以后反复使用,从而避免了从磁盘读取代码再次编译的消耗。同时,它还应用了一些代码优化模式,使得代码执行更快。从而加速 PHP 应用响应。

PHP 自 5.5 版开始,就已经内置了 OPcache 扩展。不过默认是关闭状态的。

开启 OPcache

PHP 7.2 FPM 的配置信息位于:

/etc/php/7.2/fpm/php.ini

编辑以上文件,搜索 opcache.enable 将值设为 1 即为开启

opcache.enable=1

php.ini 里相关的配置以下,注释里包括说明和推荐设置的值,请详细阅读:

; 是否在命令行开启,这里默认设置为 0 ,暂且关闭
;opcache.enable_cli=0; 这个内存是用来存储编译后的字节码的,视你的程序
; 代码量而定,Laravel 应用一般建议设置为 256,单位 MB,
; 默认是 128
opcache.memory_consumption=256; 会对程序所有的字符串进行统一存储以加快存取速度,
; 默认是 8m,建议 32 或者不超过 64。
opcache.interned_strings_buffer=32; 最大加速多少个脚本文件,视项目脚本文件数而定,
; 合理区间 200~1000000 ,默认是 10000 ,建议 500000
opcache.max_accelerated_files=1000000; 最大作废比例百分比,到达这个比例会重启,默认是 5 ,建议 10
opcache.max_wasted_percentage=10; 开启情况下会在脚本名称前加上当前目录信息做为缓存的 Key,关闭可以
; 提高性能,但是会面临出错的风险(文件名一致时),建议开启,关闭使用 0
opcache.use_cwd=1; 开启的话,会按照 opcache.revalidate_freq 设置的频率去检查文件
; 是否修改以便重新缓存,默认开启,生产环境下请设置为关闭,然后
; 写自动化脚本,在每次更新代码后自动重启 OPcache
opcache.validate_timestamps=0; 文件更新检测频率,单位秒,只有在 opcache.validate_timestamps 
; 开启时才有效。默认为 2,意味着 2 秒钟检查一次,会对文件系统造
; 成负担,如果是在开发环境中请酌情使用,生产环境随意设置,因为
; 我们会设置 validate_timestamps 为关闭。
opcache.revalidate_freq=2200; 文件加载的逻辑,默认关闭,无需修改
;opcache.revalidate_path=0; 开启的话会把代码注释一起缓存,关闭可减低内存使用,但是
; 如果有一些代码依赖于注释里的指令,例如 Doctrine, 
; Zend Framework 2 和 PHPUnit,将会出现问题。建议开启
opcache.save_comments=1

修改完成后,需要重启 FPM 生效:

sudo service php7.2-fpm restart 

生产环境下,我们一般会将 opcache.validate_timestamp 设置为 0 以获取最大性能。然后在代码变更时候,再重置 OPcache。

有两种重置 OPcache 的方法,一种是重启 FPM。此方法虽然很有效,但是会中断正在处理的请求,用户体验较差,不建议使用。

另一个方法是调用 opcache_reset() 方法,此方法会重置 OPcache 缓存并且不需要重启 FPM。然而,OPcache 是运行在 FPM 环境中的,在命令行环境中调用此函数无效。必须是一个可以通过 HTTP 访问到的脚本上来调用 opcache_reset() 才行。无法在命令行中执行。

在 laravel 中使用 OPcache ,可以直接使用 laravel-opcache

OPcache 是对 PHP 脚本的缓存,每次更改任何 PHP 代码时你都需要清除缓存


# 安装
composer require appstract/laravel-opcache# 清空 fpm 里的 OPcache
php artisan opcache:clear# 查看 OPcache 的配置信息
php artisan opcache:config# 查看 OPcache 运行状态(内存使用、缓存了多少文件等)
php artisan opcache:status# 提前编译文件
php artisan opcache:compile {--force}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/883359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SSM的“众优”大学生家教平台的设计与实现

前言 对于当今社会的人们来说,互联网技术是必不可少的,随着经济和技术的不断发展,计算机已经深入到各个领域。“众优”大学生家教平台将人们的时间需求与计算机技术结合起来,架起一座桥梁,使用在线查看“众优”大学生…

设计模式讲解

设计原则 单一职责原则 > 一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中 > //一个人类 public class People {/*** 人类会编程*/public void coding(){System.out.println("int mian() {");System.out.println(" print…

直播系统源码技术搭建部署流程及配置步骤

系统环境要求 PHP版本:5.6、7.3 Mysql版本:5.6,5.7需要关闭严格模式 Nginx:任何版本 Redis:需要给所有PHP版本安装Redis扩展,不需要设置Redis密码 最好使用面板安装:宝塔面板 - 简单好用的…

Android——事件冲突处理

当我们给列表的item设置了点击事件后&#xff0c;又给item中的按钮设置了点击事件&#xff0c;此时item的点击事件会失效。 解决 给item的布局xml中设置以下属性 android:descendantFocusability"blocksDescendants"<LinearLayout xmlns:android"http://sc…

HT7181 16.8V,14A高效升压转换器

1、特征 输入电压范围:2.7V-16V 输出电压范围:最高16.8V 固定开关频率:360kHz 可编程峰值电流:14A 高转换效率: 94% (VIN 7.2V, VOUT9.3V, IOUT1.5A) 90% (VIN 7.2V, VOUT9.3V, IOUT 7A) 93% (VIN 7.2V, VOUT12V, IOUT 1.5A) 90% (VIN 7.2V, VOUT12V, IOUT 5.5A) 90% (VIN …

220V降12V1A恒流点灯WT5112

220V降12V1A恒流点灯WT5112 芯片特点 高精度恒流输出&#xff1a;WT5112 是一款适用于非隔离降压型恒流 LED 驱动芯片。在 220V 降 12V、1A 恒流点灯应用中&#xff0c;它能够提供高精度的恒流输出。其恒流精度通常可以达到 3% - 5% 左右&#xff0c;这对于 LED 灯的稳定发光非…

安卓基础001

前言 也是好久没有更新博客了,最近实习也是需要学习一些知识哈哈哈哈哈哈为了更好的发展嘛,咱们从客户端开始,过程可能有点像写前端,不喜勿喷,希望在学习的过程中也可以给大家带来一些简单得帮助吧....... tips:这里跳过安卓studio安装,大家可自行寻找教程 写的不详细,只是为了…

从“摸黑”到“透视”:AORO A23热成像防爆手机如何改变工业检测?

在工业检测领域&#xff0c;传统的检测手段常因效率低下、精度不足和潜在的安全风险而受到诟病。随着科技的不断进步&#xff0c;一种新兴的检测技术——红外热成像技术&#xff0c;正逐渐在该领域崭露头角。近期&#xff0c;小编对一款集成红外热成像技术的AORO A23防爆手机进…

君正 T31 型号芯片架构模块介绍

文章目录 1. 核心模块2. 存储模块3. 安全模块4. 图像和视频处理5. 输入输出接口6. 其他支持模块 T31 型号 MCU 结构图&#xff1a; T31 集成了高性能 CPU、多功能图像处理单元、丰富的输入输出接口以及多种安全保护机制&#xff0c;适合用于视频监控、智能家居、工业控制等高性…

改进YOLOv8系列:引入低照度图像增强网络Retinexformer | 优化低光照目标检测那题

改进YOLOv8系列:引入低照度图像增强网络Retinexformer | 优化低光照目标检测那题 🚀论文研究概括🚀加入到网络中的理论研究🚀需要修改的代码1 🍀🍀Retinexformer 代码2🍀🍀tasks里引用🚀创建yaml文件🚀测试是否创建成功前言:这篇论文提出了一种用于低光图像…

设计模式06-结构型模式1(适配器/桥接/组合模式/Java)

#1024程序员节&#xff5c;征文# 4.1 适配器模式 结构型模式&#xff08;Structural Pattern&#xff09;的主要目的就是将不同的类和对象组合在一起&#xff0c;形成更大或者更复杂的结构体。结构性模式的分类&#xff1a; ​ 类结构型模式关心类的组合&#xff0c;由多个类…

项目部署 —— 前端、后端

一、 前端 ● 二号标题 在命令框里输入 npm run build 打包成功&#xff1a; 项目就会出现一个 dist 文件夹 将Linux的nginx文件夹中&#xff0c;重命名为 news 二、 后端 ● 通过maven打包后端程序 最终会在项目中生成一个 target 文件夹&#xff0c;将 news-1.0-SNAPSHOT.…

Python爬虫,初识xpath(1)

xpath解析 抓取主页面当中所有壁纸的链接地址 xpath是专门针对xml而创建的表达式语言&#xff0c;可以直接从xml中提取表达式数据&#xff1b;也可以取html取数据&#xff1b;html是xml的子集。 1.按照lxml安装包 在python终端输入 pip install lxml from lxml import etre…

【element-tiptap】如何实现查找替换功能?

这是一个稍微复杂的功能了&#xff0c;因为 element-tiptap 中没有查找替换功能&#xff0c;需要从零开始开发。但是&#xff0c;在万能的github上有一个开源的库&#xff0c;我们可以借用一下 tiptap-search-and-replace 不过这个库是没有UI的&#xff0c;只有一个扩展的方法。…

【Linux】线程池详解及其基本架构与单例模式实现

目录 1.关于线程池的基本理论 1.1.线程池是什么&#xff1f; 1.2.线程池的应用场景&#xff1a; 2.线程池的基本架构 2.1.线程容器 2.2.任务队列 2.3.线程函数&#xff08;HandlerTask&#xff09; 2.4.线程唤醒机制 3.添加单例模式 3.1.单例模式是什么&…

【 thinkphp8 】00006 启动 内、外置服务器

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【 t…

Linux文件类型和根目录结构

Linux文件类型和根目录结构 1.文件类型 字符文件类型说明~普通文件类似于Windows的记事本d目录文件类似于windows文件夹c字符设备文件串行端口设备&#xff0c;顺序读写&#xff0c;键盘b块设备文件可供存储的接口设备&#xff0c;随机读写&#xff0c;硬盘p管道文件用于进程…

jmeter中请求参数:Parameters、Body Data的区别

使用jmeter发送请求&#xff0c;常常要伴随传递参数。有两种请求参数: Parameters, Body Data, 它们的使用方式有很大不同。 先看下get和post请求的区别。 get请求&#xff1a;顾名思义是从服务器获取资源。 post请求&#xff1a;顾名思义是往服务器提交要处理的数据。 直观…

【算法刷题指南】双指针

&#x1f308;个人主页&#xff1a; 南桥几晴秋 &#x1f308;C专栏&#xff1a; 南桥谈C &#x1f308;C语言专栏&#xff1a; C语言学习系列 &#x1f308;Linux学习专栏&#xff1a; 南桥谈Linux &#x1f308;数据结构学习专栏&#xff1a; 数据结构杂谈 &#x1f308;数据…

JavaSE要点 1】Java基础

目录 一、编译和运行 二、JDK,JRE和JVM 三、Java中的基本类型 1. 基本类型的大小 四、JVM内存模型 1. 内存模型 五、JVM虚拟机的组成 1. 虚拟机的5个组成部分 2. 虚拟机栈 3. 栈帧 六、值传递和引用传递 七、变量的默认值 八、String的不可变 九. 包装类和常量池&#xff08;-…