php性能优化方案(如何通过php-fpm来提升php的性能?)

php的性能优化一直是很多中小型网站特别关注的一个问题点,特别是当数据量达到百万级别的时候,就需要为后端的查询次数进行优化了,本文就围绕着php的性能和php的高并发做一个技术上的探讨。

PHP是无处不在的,可以说是互联网 Web 应用上使用最广泛的语言。

然而,它的高性能并不为人所知,尤其是在涉及到高并发系统时。这就是为什么对于这样特殊的用例,正在被 Node (是的,我知道,它不是一种语言)、Go 和 Elixir 等语言接管。

也就是说,您可以做很多事情来改进服务器上的 PHP 性能。本文主要关注 php-fpm 方面的内容,如果您使用Nginx,这是在服务器上的默认配置。

如果你知道 php-fpm 是什么,请直接跳到优化部分。

什么是 php-fpm?

许多开发人员对 DevOps 方面的知识不太感兴趣,即使是那些对此感兴趣的开发人员,也极少有人知道它的底层原理。有趣的是,当浏览器发送一个请求到运行 PHP 的服务器上时,PHP 也不是最先进行处理请求的服务;而是,HTTP 服务器,Apache 和 Nginx 是其中最主要的两个。「web 服务器」决定如何与 PHP 进行通信,然后传递请求的类型,数据和头部信息到 PHP 进程。

phpfpm

上图是 PHP 项目的请求-响应生命周期(图片来源: ProinerTech)

在现代 PHP 应用中,「find file」部分即为 index.php 文件,它是在服务器配置文件中配置的用于处理所有请求的代理。

如今,Web 服务器究竟如何连接 PHP 正在进化,如果我们要深入研究所有细节,这篇文章的长度将激增。但粗略来说, 在 Apache 作为 Web 服务器首选的时间段,PHP 是作为包含在服务器内部的模块。

所以每当一个请求被接收,服务器将开启一个新的进程, 它将自动包含 PHP 和执行请求。这个方法被称作mod_php,“PHP作为一个模块”的缩写。这种方法有其局限性,而 Nginx 和 php-fpm 克服了它。

在php-fpm中,管理 PHP 的责任在于服务器内部的 PHP 程序。换言之, Web 服务器 (Nginx, 在本例中), 不在乎 PHP 在哪和怎样运行的,只要它知道如何发送和接收数据即可。如果需要,在这种情况下,您可以将PHP视为另一台服务器,它管理传入请求的某些子PHP进程(因此,我们将请求送到服务器,该请求由服务器接收并传递到服务器 — —太疯狂了!:-P)。

如果你用过Nginx,你会看到这些代码:

location ~ \.php$ {

try_files $uri =404;

fastcgi_split_path_info ^(.+\.php)(/.+)$;

fastcgi_pass unix:/run/php/php7.2-fpm.sock;

fastcgi_index index.php;

include fastcgi_params;

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

}

对于这一行:fastcgi_pass unix:/run/php/php7.2-fpm.sock;,它告诉Nginx通过 php7.2-fpm.sock的socket与php进程通信。因此,对于每个传入的请求,Nginx都通过这个文件写入数据,在接收到输出后,将其发送回浏览器。

我必须再次强调,对于如何运行这不是最完整或者最准确的,但对于大多数 DevOps 任务是完全准确的。

除此之外,让我们回顾一下到目前为止所学到的东西:

PHP不会直接接收浏览器发送的请求。像 Nginx 这种 Web 服务器首先会拦截它。

Web 服务器知道如何连接到PHP进程,并将所有请求数据(粘贴所有内容)传递到 PHP 上。

PHP 完成其职责后,会将响应发送回 Web 服务器,然后将其发送回客户端(在大多数情况下为浏览器)。

流程图如下:

phpfpm1

PHP 和 Nginx 如何协同工作? (图片来源:数据狗)

到目前为止都不错, 那么关键问题来了:PHP-FPM到底是什么呢?

PHP 中的 FPM 代表 「快速进程管理器」, 花式解释就是说,在服务器上运行的 PHP 并不是单个进程,而是由这个 FPM 进程管理器派生、控制和终止的一些PHP 进程。web服务器将请求传递给的就是这个进程管理器。

PHP-FPM 本身就是一个完整的兔子洞,所以如果您愿意,可以随意探索,但是对于我们的目的,这些解释就足够啦。 ?

为什么要优化php-fpm?

一般在正常运行的情况下,为什么要考虑优化呢? 为什么不将事物保持原样。

具有讽刺意味的是,一般我为大多数用例提供建议的话。 如果您的设置运行良好,并且没有特殊用例,请使用默认设置。 但是,如果您希望扩展一台机器之外的能力,那么从一台机器中挤出最大的处理能力是必不可少的,因为它可以将您服务器的花费减少一半(甚至更多!)。

要说明的另一件事情是,Nginx是为处理巨大的工作负载而构建的。 它能够同时处理成千上万的连接,但是如果您的PHP设置不合理,那么您将浪费很多资源,因为Nginx必须等待PHP完成当前处理之后才可以接受下一个请求,最终Nginx不能为您的服务提供任何优势!

所以,接下来让我们看看尝试优化 php-fpm 时我们到底要优化什么。

如何优化 PHP-FPM ?

php-fpm 的配置文件在不同服务器上的位置可能不同,因此您需要做一些调查来确定它的位置。在 UNIX 上,你可以使用 find 命令。在我的 Ubuntu 上,它的路径是 /etc/php/7.2/fpm/php-fpm.conf 。当然,7.2是我正在运行的 PHP 版本。

下面是这个文件的前几行代码:

;;;;;;;;;;;;;;;;;;;;;

; FPM Configuration ;

;;;;;;;;;;;;;;;;;;;;;

; All relative paths in this configuration file are relative to PHP’s install

; prefix (/usr). This prefix can be dynamically changed by using the

; ‘-p’ argument from the command line.

;;;;;;;;;;;;;;;;;;

; Global Options ;

;;;;;;;;;;;;;;;;;;

[global]

; Pid file

; Note: the default prefix is /var

; Default Value: none

pid = /run/php/php7.2-fpm.pid

; Error log file

; If it’s set to “syslog”, log is sent to syslogd instead of being written

; into a local file.

; Note: the default prefix is /var

; Default Value: log/php-fpm.log

error_log = /var/log/php7.2-fpm.log

很明显:这一行 pid = /run/php/php7.2-fpm.pid 告诉我们哪个文件包含了 php-fpm 进程的进程 id。

我们还看到 /var/log/php7.2-fpm.log 是 php-fpm 存储日志的地方。

在这个文件中,像下面这样添加三个变量:

emergency_restart_threshold 10

emergency_restart_interval 1m

process_control_timeout 10s

前两个设置是警告性的,它们告诉 php-fpm 进程,如果10个子进程在一分钟内失败,主 php-fpm 进程应该重新启动自己。

这听起来可能不够稳健,但是 PHP 是一个短暂的进程,它会泄漏内存,所以在出现高故障时重新启动主进程可以解决很多问题。

第三个选项是 process_control_timeout,它告诉子进程在执行从父进程接收到的信号之前需要等待这么长的时间。这个设置是非常有用的。例如,当父进程发送终止信号时,子进程正在处理某些事情的时候。十秒的时间,他们会有一个更好的机会完成任务并且优雅地退出。

令人惊讶的是,这 不是 php-fpm 的核心配置!这是因为,为了 web 请求服务,php-fpm 创建了一个新的进程池,它将具有一个单独的配置。在我的例子中,进程池的名称是 www,我想编辑的文件是 /etc/php/7.2/fpm/pool.d/www.conf。

让我们来看看文件的内容:

; Start a new pool named ‘www’.

; the variable $pool can be used in any directive and will be replaced by the

; pool name (‘www’ here)

[www]

; Per pool prefix

; It only applies on the following directives:

; – ‘access.log’

; – ‘slowlog’

; – ‘listen’ (unixsocket)

; – ‘chroot’

; – ‘chdir’

; – ‘php_values’

; – ‘php_admin_values’

; When not set, the global prefix (or /usr) applies instead.

; Note: This directive can also be relative to the global prefix.

; Default Value: none

;prefix = /path/to/pools/$pool

; Unix user/group of processes

; Note: The user is mandatory. If the group is not set, the default user’s group

; will be used.

user = www-data

group = www-data

快速浏览一下上面代码片段的末尾,您就会明白为什么服务器进程以 www-data 的形式运行了。如果您在设置网站时遇到文件权限问题,您可能要将目录的所有者或组更改为 www-data,从而允许PHP进程写入日志文件和上传文档等。

最后,我们到达了问题的根源,流程管理器 (pm) 设置。一般情况下,默认值是这样的:

pm = dynamic

pm.max_children = 5

pm.start_servers = 3

pm.min_spare_servers = 2

pm.max_spare_servers = 4

pm.max_requests = 200

那么,这里的 「dynamic(动态)」是什么意思呢?我认为官方文档最好地解释了这一点(我的意思是,这应该已经是您正在编辑的文件的一部分,但是我在这里复制了它,以防它不是):

; Choose how the process manager will control the number of child processes.

; Possible Values:

; static – a fixed number (pm.max_children) of child processes;

; dynamic – the number of child processes are set dynamically based on the

; following directives. With this process management, there will be

; always at least 1 children.

; pm.max_children – the maximum number of children that can

;be alive at the same time.

; pm.start_servers – the number of children created on startup.

; pm.min_spare_servers – the minimum number of children in ‘idle’

;state (waiting to process). If the number

;of ‘idle’ processes is less than this

;number then some children will be created.

; pm.max_spare_servers – the maximum number of children in ‘idle’

;state (waiting to process). If the number

;of ‘idle’ processes is greater than this

;number then some children will be killed.

; ondemand – no children are created at startup. Children will be forked when

; new requests will connect. The following parameter are used:

; pm.max_children – the maximum number of children that

; can be alive at the same time.

; pm.process_idle_timeout – The number of seconds after which

; an idle process will be killed.

; Note: This value is mandatory.

由此可见,有三个可用值:

Static: 无论什么情况,都会保持一个固定的PHP进程数量。

Dynamic: 我们需要指定php-fpm在任何给定时间点会保持活动的最小以及最大进程数量。

ondemand: 按照需求创建和销毁进程。

那这些设置有什么影响呢?

简而言之,如果你有个小流量的网站,“dynamic”设置在大多数时间内都是一种资源的浪费。假设你的pm.min_spare_servers设置成了3,那会有三个PHP进程会被创建并保持运行,甚至是网站没有流量时。这种情况下,“ondemand”就是个更好的选择, 可以让系统决定何时启动新的进程。

另一方面, 大流量 或者必须快速响应的网站将在这种情况下被惩罚。 最好避免创建新的 PHP 进程的额外开销,使其成为池的一部分并对其进行监控。

使用 pm = static 固定子进程的数量,使最大的系统资源用于服务请求而不是管理 PHP。假如你确定走这条路,注意它有其指导方针和陷阱.关于它的一篇相当密集但非常有用的文章是 这篇 。

小结

由于有关网络性能的文章可能会引发争论或使人们感到困惑,因此在结束本文之前,我觉得需要讲几句话。 性能调优既涉及系统知识,也涉及猜测和技巧。

即使您完全了解php-fpm的所有设置,也无法保证成功。如果您不了解php-fpm的存在,那么您就不必浪费时间担心它。继续做您已经在做的事情并继续下去。

同时,尽可能不让结果变得很戏剧性。 是的,您可以通过从头开始重新编译 PHP 并删除所有不需要的模块来获得更好的性能,但是这种方法在生产环境中不够明智。优化某些内容的整个想法是查看您的需求是否与默认值不同(它们很少这样做!),并根据需要进行较小的更改。

php优化网站加载速度

1、减少页面请求:

从WEB运行原理上讲,IIS请求是无状态的,在服务器端一直是连接和关闭的不断进行着,如果能减少服务器请求,总的时间将会减少。

之前我下载163邮箱的登陆页面的图片时发现,它们的只用到了一个图片来完成整个页面的所有图片,当时我就纳闷了,这跟平时做的网站不一样呀。然来这样做减少浏览器的请求次数,用httpwatch你会发现请求的总时间大大减少了。同样的想法,在做css样式,JavaScript代码的时候也要做到尽可能的放在一个文件下来减少WEB请求。

2、页面压缩技术,给我们JS,HTML代码进行瘦身。

jQuery 作为JS最轻量级的类库,它的原类库是242KB,压缩后的它竟只有91.6KB。 常见的压缩工具有Google Closure Compiler、YUI Compressor、JsPacker、gzip。我常用的是gzip,因为它的压缩率是最高的。用jdk压缩后它会把一些空格去掉,把我们很长的变量名换成换成很短的字母来代替。

3、样式、行为、结构分离。

当第一次访问页面的时候,用户就可以把CSS,JS代码下载下来,这样做虽然第一次使网页加载的速度变慢了,但后面的页面将快很多。当用户访问这个网站的其它的页面时,由于其它页面也引用了这个CSS样式和JS代码。浏览器发现它已经下载好了,下一次就可以不用下载了。这样就做到了一次下载,后续速度的效果。

4、使用存储过程

在运行存储过程前,数据库已对其进行了语法和句法分析,并给出了优化执行方案。这种已经编译好的过程可极大地改善SQL语句的性能。由于执行SQL语句的大部分工作已经完成,所以存储过程能以极快的速度执行。这种预编译的sql语句就可以直接执行而节省了很大一部分查询的时间。

5、一些细节:

把CSS样式放在头部,如果JS很多的话,把js代码放在尾部。这样做可以尽可能的先加载页面的DOM结构,然后才可以级用户体验。如果JS很多的大的话,页面都没加载完,何来用户体验之说呢。

6、适当的使用AJAX

现在的Ajax好像有点被神话了,好像网页只要Ajax了,那么就不存在效率问题了。其实这是一种误解。拙劣的使用Ajax不会让你的网页效率更高,反而会降低你的网页效率。Ajax的确是个好东西,但是请不要过分的神话它。使用Ajax的时候也要考虑上面的那些准则。

7、尽量少使用样式工具为我们生成的页面样式代码,自己动手把样式写在样式文件里。尽量写得通用些。

8、页面缓存

在大型的门户网站都用到了缓存技术,它是以空间换时间的技术。

缓存主要是为了提高数据的读取速度。因为服务器和应用客户端之间存在着流量的瓶颈,所以读取大容量数据时,使用缓存来直接为客户端服务,可以减少客户端与服务器端的数据交互,从而大大提高二次页面的访问速度的程序的效率。

9、配置网站的实体标签

这个Etag不是给用户用的,而是给浏览器缓存用的。Etag是服务器告诉浏览器缓存,缓存中的内容是否已经发生变化的一种机制。通过Etag,浏览器就可以知道现在的缓存中的内容是不是最新的,需不需要重新从服务器上重新下载。

10、使用CDN技术。

我们上网下载东西的时候经常会看见什么“南方服务器”、“北方服务器”的就是用到了CDN技术来提高下载速度与稳定性。

CDN的全称是Content Delivery Network,即内容分发网络。其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度(来自百度百科)。

11.使用Gzip压缩文档

GZIP编码是用来改进网页性能的方法,不仅可以减小存储空间,还可以减少传输所需的时间。将网站中的文件使用Gzip压缩后,可以显著的增加网页加载速度,同时也可以降低网站的带宽流量消耗。

12.样式表文件放在外部调用

把页面中需要用到的JavaScript和CSS样式表文件放在另外的文件夹中,这样一来在打开网站其它页面时就会缓存这些调用的文件,从而加快网站页面的加载速度。

13.给JavaScript文件减肥

这个方法不同于gzip压缩功能,缩小JavaScript文档有很多方法,比如去除不必要的空格等其他标签等。减少脚本文件后可以显著的提高网页的访问速度。

14.图片使用height和width属性

每个图片的height和width属性可以让浏览器在加载图片之前就知道图片的长和宽,并预留出指定的长宽待图片加载后显示。如果没有这两个属性,浏览器还需要在读取图片成功后再处理一次页面布局样式,这无疑减慢了网页加载速度。所以在固定图片大小的情况下最好都使用上长和宽属性。

15.CSS文件压缩瘦身

DIV+CSS是现在流利的网页布局方式,DIV定义了元素,CSS控制显示效果。所以往往我们会把CSS写到另外一个或多个外部链接CSS文件中,并且CSS文件代码也有很多行。我们可以使用一些CSS压缩工具来删除CSS文件中不必要的多余内容,如重复定义样式、空格等来瘦身。可以尝试使用一下CleanCSS工具来压缩你的CSS文件。

16.整合CSS、JS文件减少HTTP请求次数

现在的网页都有多个图片、CSS外部文件链接、Javascript外部脚本链接。所以当访问一个网页时浏览器需要多次向服务器请求这些文件。在请求和加载之间会产生不少的时间差。特别是一些网页上有多个小图片、图标按钮的网页,有多少图片,浏览器就需要请求多少将这些小文件,多将请求这些小图片文件将明显影响网页的加载速度。所以我们应该尽可能将小图片拼合一个PNG大图片上,然后通过坐标来显示图标。一次请求一个大图片比多次请求小
图片速度要快不少。同样,最好将CSS和Javascript尽可能地整合到一个文件中都有助于加快网页载入速度。

17.目录地址后加上斜杠(/)

如访客点击访问这样一个目录地址:https://www.qin1qin.com/fuwu,去打开这个目录下的index.html文档。当服务器收到请求后它需要消耗一些时间来分析这是一个文件还是一个目录。但是如果我们在最后加上一个斜杠(/
),服务器就知道你是在访问一个目录地址,然后就直接加载默认文档index.html或index.PHP就行了。这样服务器就不用花时间来分析这个地址,也起到了一定加速的作用。

php高并发三种解决方法

1、应用和静态资源分离

将静态资源(js,css,图片等)放到专门的服务器中。

2、页面缓存

将应用生成的页面缓存起来可以节省大量cpu资源。对于部分页面经常变换数据的,可以使用ajax来处理。

3、集群和分布式

集群,多台服务器具有相同的功能,主要起分流的作用。分布式,将不同的业务放到不同的服务器中,处理一个请求可能需要多台服务器,进而提高一个请求的处理速度。又分为静态资源集群和应用程序集群。后者较复杂,经常要考虑session同步等问题。

4、反向代理

客户端直接访问的服务器并不是直接提供服务的服务器,它从别的服务器获取资源,然后将结果返回给用户。

代理服务器和反向代理服务器:

代理服务器是代我们访获取资源,然后将结果返回。例如,访问外网的代理服务器。反向代理服务器是我们正常访问一台服务器的时候,服务器自己调用了别的服务器。

代理服务器我们主动使用,是为我们服务的,不需要有自己的域名;反向代理是服务器自己使用的,我们并不知道,有自己的域名。

5、CDN

CDN是一种特殊的集群页面缓冲服务器,和普通的集群的多台页面缓冲服务器相比主要区别是:其存放位置和分配请求方式不同。

CDN的服务器分布在全国各地,接收到请求后会将请求分配到最合适的CDN服务器节点来获取数据。其每一个CDN节点就是一个页面缓存服务器。

分配方式:

并不是普通的负载均衡,而是专门的CDN域名解析服务器在解析域名的时候就分配好的。

一般的做法是:ISP那里使用CNAME将域名解析到一个特定的域名,然后再将解析到的那个域名用专门的CDN服务器解析(返回给浏览器,再访问)到相应的CDN节点。每个节点可能也集群了多台服务器。

你可以知道处理高并发的业务逻辑是:

前端:异步请求+资源静态化+cdn

后端:请求队列+轮询分发+负载均衡+共享缓存

数据层:redis缓存+数据分表+写队列

存储:raid阵列+热备

网络:dns轮询+DDOS攻击防护

总结一下:尽管现在python,.net C语言都非常的火,但是php是也还是会受到很多中小企业的追捧,对php合理的设置,优化,访问速度这一块是完全可以达到秒开的,减少php后端的查询次数,增加php的缓存,都可以给php带来极速的体验。

本文来自投稿,不代表(钦钦技术栈)立场,如若转载,请注明出处:https://www.qin1qin.com/catagory/406/

(0)
上一篇 2022年6月24日 下午10:26
下一篇 2022年6月24日 下午11:00
软件定制开发公司

相关阅读

发表回复

登录后才能评论
通知:禁止投稿所有关于虚拟货币,币圈类相关文章,发现立即永久封锁账户ID!