您的当前位置:首页>全部文章>文章详情

【PHP】从服务器负载一路走到PHP-FPM优化终于搞定了PHP项目偶尔很慢的问题

CrazyPanda发表于:2024-06-21 10:59:50浏览:260次TAG:

原文链接https://zhuanlan.zhihu.com/p/681575918

项目情况: 阿里云Rds 阿里云Redis PHP8 IN Docker

本文会从几个方面来讲PHP线上项目怎么进行性能瓶颈定位,以及优化方法。

前段时间有个PHP项目开始出现偶尔有一些请求会超时,最长的请求可能需要长达20S。 一般出现这总情况的时候,我们首先想到的会不会服务器负载不够,或者个某个查询花了太多时间。

观察服务器负载

  • 服务器负载 30% 左右,一切正常

  • 数据库负载 60% 左右,一切正常

  • Redis负载 30% 左右,一切正常

首先排除了是因为服务器负载的原因,那么接下来想到的就是 Mysql 部分查询很慢导致的。

检查数据库负载以及 Sql慢查询

  • 数据库负载一切正常,当看到这个情况的时候我们心里其实排除了是数据库的原因了。

  • 继续查看 Sql慢日志,发现有一些日志,都是1-2 秒之间,没有什么特别需要关心的。

这里也排除了数据库的原因,接下来继续查看 Nginx情况。

检查 Nginx 日志

这里检查 Nginx 日志主要是查询是否又Http 状态码 是429这样的请求,如有出现很频繁,那么表示是 Nginx Worker不够,或者是 PHP程序内部返回的 429。其实我们这次的原因可以排除是这个可能,因为如果是这个问题,那么那么请求不应该很慢,应该会直接返回错误码。那么当我们遇到Nginx返回429我们一般怎么处理呢。

429 (Too Many Requests)

首先我们要知道什么时候 Nginx会返回这个错误码:在Nginx服务器中遇到HTTP状态码429(Too Many Requests)时,通常意味着客户端在短时间内发送了过多的请求,超出了服务器允许的速率限制。

常用解决方案

一、调整 Nginx worker_processesworker_connections

首先检查worker_processesworker_connections看看设置的大小是多少

worker_processes它定义了Nginx要启动的工作进程(worker process)的数量。工作进程是实际处理客户端请求的核心单元,负责接收和处理HTTP请求、读写磁盘上的文件以及与上游服务器通信等任务。通过设置多个工作进程,Nginx可以充分利用多核CPU的优势,分散负载到不同的核心上并行处理请求,从而提高系统的并发处理能力和整体性能。

自动检测CPU核心数,并设置相应数量的工作进程(推荐)
worker_processes auto;
如果你的服务器是4核CPU或多核CPU但希望限制为使用4个核心,当然我们通常可以设置到 2-3 倍,比如 8 或者 12.
worker_processes 4;

worker_connections 是 Nginx 服务器配置中的一个重要参数,它定义了每个工作进程(worker process)可以同时处理的最大并发连接数。这个设置直接影响到Nginx服务器能够同时服务的客户端请求数量。每一个工作进程都有一个最大连接数的限制,超过这个限制后,新的连接将无法被接收和处理。合理设置 worker_connections 可以有效利用系统资源,避免因并发连接数过大导致内存溢出或其他资源耗尽问题。

worker_rlimit_nofile 10240;
events {
    use epoll; # 对于Linux环境,推荐使用epoll事件模型
    multi_accept on; # 允许一个工作进程接受多个连接
    worker_connections 6144; # 每个工作进程允许的最大并发连接数
}

这里设置的是每个工作进程可同时处理的并发连接数为6144。实际应用中,根据服务器硬件性能、操作系统参数(如打开文件描述符数量上限)、以及预期业务负载进行调整。另外,在设置 worker_connections 参数时,需要确保其值小于或等于 worker_rlimit_nofile 参数设置的值(即每个工作进程允许打开的最大文件描述符数量),因为每个网络连接都需要占用一个文件描述符。 worker_rlimit_nofile 指令用于设置每个工作进程可以打开的最大文件描述符数量,这对于处理高并发连接至关重要。当Nginx作为Web服务器或反向代理时,它需要为每个活动连接保持一个打开的文件描述符(例如套接字)。如果这个限制过低,可能会导致无法处理更多的客户端连接,即使系统资源充足。 那么如何设置worker_rlimit_nofile ,对于worker_rlimit_nofile的设置我们可以参考系统自身最大打开文件数。

ulimit -n
65535

这里最大为 65535 所以我们可以设置为65535 .但是如果直接把worker_rlimit_nofile 设置到65535,如果请求过大的时候可能就会影响其他的进程。

二、限速限流

可以对某一个 IP 进行限流限速,这样可以排除一些异常的请求。也可以保障其他请求的正常执行。

二、负载均衡与扩展性考虑:

如果是因为服务器处理能力达到瓶颈,可以考虑负载均衡技术,将流量分散到多个服务器上,或者根据需要扩展服务器资源。

检查PHP-FPM

当服务器,数据库,Nginx都正常之后,我就想到最后的一个可能,PHP-FPM进程不能够用了。 查看 Docker 默认的FPM进程配置

cat /usr/local/etc/php-fpm.d/www.conf

pm = dynamic

; The number of child processes to be created when pm is set to 'static' and the
; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
; CGI. The below defaults are based on a server without much resources. Don't
; forget to tweak pm.* to fit your needs.
; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
; Note: This value is mandatory.
pm.max_children = 5

; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: (min_spare_servers + max_spare_servers) / 2
pm.start_servers = 2

发现默认只有 最大只有 5 个进程,所以我们增大到 20 个,修改配置如下

pm = dynamic
pm.start_servers = 5
pm.max_children = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500
pm.process_idle_timeout = 10s

由于这里使用的Docker ,所以我们尽量使用挂载配置文件的方式来修改配置,使用Docker-compose 来挂载新增的php配置zz-docker.conf

volumes:
      - "./docker/php/zz-docker.conf:/usr/local/etc/php-fpm.d/zz-docker.conf:cached"

最后重启Docker,通过一周观察,一切回到正常状态。

最后:常用的PHP-FPM各个参数的含义以及配置

PHP-FPM(参数优化是提高服务器性能和稳定性的关键步骤之一,以下是一些主要的PHP-FPM配置参数及其优化建议:

  1. 进程管理方式 (**pm**):

  • pm = static: 静态模式,固定数量的子进程。

pm.max_children = N # 设置最大子进程数
  • pm = dynamic: 动态模式,根据负载自动调整子进程数量。

pm.max_children = N # 最大子进程数
pm.start_servers = M # 启动时创建的进程数
pm.min_spare_servers = X # 空闲时最小进程数
pm.max_spare_servers = Y # 空闲时最大进程数
  1. 子进程数量 (**max_children**): 根据服务器内存大小和单个PHP请求的平均内存消耗计算出合适的值。确保所有子进程占用的总内存不超过服务器物理内存的75%左右并需要根据实际情况调整,以免出现内存溢出。

  2. 请求处理超时 (**request_terminate_timeout**):

request_terminate_timeout = T # 请求处理超时时间(秒)

设定一个合理的脚本执行超时时间,防止因个别耗时过长的请求导致资源浪费或服务卡顿。

  1. 监听队列 (**listen.backlog**):

这个参数决定了等待连接队列的最大长度,可以根据系统负载和并发需求进行适当调整。

  1. 错误日志级别 (**log_level**):

log_level = notice # 或 error, warning, debug等

选择适当的日志级别以平衡调试需要与减少日志输出对性能的影响。

  1. 慢日志记录 (**slowlog**):

slowlog = /path/to/slow.log
request_slowlog_timeout = S # 超过多少秒的请求会被记录到慢日志

记录执行时间过长的请求,帮助分析和优化代码。

每个参数的优化都需要结合实际情况,如服务器硬件资源、网站访问量特点以及PHP应用程序的具体行为等因素综合考虑,并且可能需要反复测试和调优。

猜你喜欢

【PHP】php7.4安装zipArchive,使用ZipArchive类的问题及解决方法
一、问题描述在开发过程中,有时会遇到PHP报错提示"Class ZipArchive not found",这是因为PHP的ZipArchive类没有被正确加载导致的。二、具体步骤及代码步骤1:确认环境在开始解决问题之前,我们需要确认一下当前环境是否满足使用ZipArchive类的要求。首先,我们需要检查PHP版本是否符合要求,一般来说,PHP版本需要大于等于5.2.0才能使用ZipArchive类。可以通过以下代码来检查PHP版本:<?php   
发表于:2024-01-31 浏览:344 TAG:
【PHP】php8为什么性能高
hp8性能高的原因:php8引入了JIT编译器、优化了函数调用、数组操作、引入了新的数据结构和算法,并修复和优化了一些内部实现细节等等。详细介绍:1、引入了Just-In-Time(JIT)编译器,JIT编译器是一种动态编译技术,它将PHP代码转换为机器码,以便更高效地执行;2、优化了函数调用,在PHP8中,通过引入函数调用的内联缓存(IC)机制,可以避免昂贵的开销等等。本教程操作系统:windows10系统、PHP8版本、Dell G3电脑。PHP是一种广泛使用的服务器端脚本语言,用于开发W
发表于:2023-12-30 浏览:321 TAG:
【PHP】php有哪些爬虫模块类型
hp爬虫模块类型有cURL、Simple HTML DOM、Goutte、PhantomJS、Selenium等等。详细介绍:1、cURL,可以模拟浏览器行为轻松地获取网页内容;2、Simple HTML DOM,可以通过CSS选择器或XPath表达式来定位和提取HTML元素,方便地从网页中提取所需的数据;3、Goutte可以发送HTTP请求、处理Cookie、处理表单等等。本教程操作系统:Windows10系统、PHP8.1.3版本、Dell G3电脑。PHP作为一种流行的编程语言,具有强大
发表于:2023-12-04 浏览:638 TAG:
【PHP】php手动加载vendor第三方库
方式一:手动配置autoload文件方式二:在composer.json 中 调整 autoload场景不知道做php开发的小伙伴有没有遇到这样的痛点:使用第三方框架时安装的依赖包,你接手时候执行 composer update/insetall 时候总是超时或者安装时候总是报某个依赖包于其冲突。导致浪费大量时间去调整,最终无功而返。场景复现:我在一个旧的项目包上,想下载一个依赖包,执行安装时,总是包版本和现在不兼容或者一些依赖的问题。切换了镜像也是如此,所以考虑不如手动安装来的快~方案只需要手
发表于:2024-03-01 浏览:356 TAG:
【PHP】php如何创建关联数组表格
随着互联网技术的不断发展,Web 应用程序的开发变得越来越重要。其中,关联数组表格是 Web 应用程序中常用的一种数据结构,它可以将数据按照列与行的方式分组存储,并且可以方便地在前端界面中进行展示。那么,如何使用 PHP 创建关联数组表格呢?本文将为您一一介绍。一、创建关联数组在 PHP 中,我们可以使用关联数组来存储数据,关联数组是以字符串为索引的数组。相较于索引数组(使用数字作为索引的数组),关联数组更加灵活,可以通过索引来直接访问每个元素。下面的示例代码创建了一个关联数组,包含了
发表于:2023-12-18 浏览:331 TAG:
【PHP】如何在PHP中使用Imagick库处理图片?
引言:在Web开发中,经常需要对图片进行处理和优化,Imagick是一个强大的PHP扩展库,可以实现各种图片处理操作,比如图片裁剪、缩放、旋转、添加文字等。本文将介绍如何使用Imagick库在PHP中处理图片,并给出具体的代码示例。一、安装Imagick库1.确认是否已安装Imagick库在终端中输入以下命令,查看是否已安装Imagick库:php -m | grep imagic登录后复制登录后复制如果没有输出,则说明未安装Imagick库,需要进行安装
发表于:2024-03-25 浏览:359 TAG:
【PHP】PHP面试题
1、什么事面向对象?主要特征是什么?面向对象是程序的一种设计方式,它利于提高程序的重用性,使程序结构更加清晰。主要特征:封装、继承、多态。2、SESSION 与 COOKIE的区别是什么,请从协议,产生的原因与作用说明?A、http无状态协议,不能区分用户是否是从同一个网站上来的,同一个用户请求不同的页面不能看做是同一个用户。B、SESSION存储在服务器端,COOKIE保存在客户端。Session比较安全,cookie用某些手段可以修改,不安全。Session依赖于cookie进行传递。禁用c
发表于:2024-05-21 浏览:263 TAG:
【PHP】php怎么将汉字转为拼音
PHP是一种非常流行的服务端脚本语言,它具有灵活、快速、安全等优点,因此被广泛应用于Web开发、互联网应用和企业级软件开发等领域。而将汉字转为拼音是一个常见的需求,特别是在中文搜索、排序、筛选等场景下,可以提高用户体验和检索准确性。本文将介绍如何使用PHP实现将汉字转为拼音的方法。一、使用PHP拓展PHP中有一个名为pinyin的拓展,通过它可以很方便地将汉字转为拼音。首先需要在php.ini文件中开启拓展,找到下面这行并取消注释,保存并重启PHP服务:extension=pinyin.so登录
发表于:2024-01-05 浏览:321 TAG:
【PHP】如何优化ThinkPHP的URL访问方式
开发建议:如何优化ThinkPHP的URL访问方式引言:ThinkPHP是一款功能强大的PHP框架,广泛应用于Web开发领域。在进行Web开发时,良好的URL访问方式对于用户体验和搜索引擎优化至关重要。本文将介绍一些优化ThinkPHP的URL访问方式的建议,帮助开发者提升网站的性能和可维护性。一、使用路由功能ThinkPHP提供了强大的路由功能,可以帮助我们定义URL的访问规则,并将不同的URL映射到对应的控制器和操作方法上。合理使用路由功能,可以让URL更加友好和直观,提高用户体验
发表于:2023-12-08 浏览:341 TAG:
【PHP】php对象和数组区别是什么
php对象和数组区别是:1、对象是一个复合数据类型,而数组是一个简单的数据类型;2、对象的属性和方法可以通过对象的实例来访问,而数组的元素可以通过索引来访问;3、对象是一个封装了属性和方法的实体,而数组是一个有序的元素集合;4、对象在PHP中是通过引用来传递的,而数组在PHP中是通过值来传递的;5、对象适用于描述具有状态和行为的实体,而数组适用于存储和处理大量的相似数据。本教程操作环境:windows10系统、php8.1.3版本、DELL G3电脑。PHP是一种面向对象的编程语言,它
发表于:2023-12-06 浏览:366 TAG: