Code前端首页关于Code前端联系我们

PHP在生产中,设置高并发

terry 2年前 (2023-09-24) 阅读数 54 #后端开发

PHP在生产中需要优化,让PHP本身能够有更好的表现。除了编写PHP代码外,还需要配置php-fpm和php.ini。本文介绍了如何从内存、OPcache、上传、会话和安全方面调整 php.ini 配置。

与其他编译型语言相比,PHP最大的缺点是每个请求都需要某个模块进行解析并实际执行工作流程。启动工作进程需要更多资源。同时,每次请求都会重新解析一些代码,导致重复解析。

PHP优化你可以围绕这方面来考虑优化。

内存优化

运行 PHP 时,需要考虑每个 PHP 进程使用了​​多少内存。 php.ini中的memory_limit用于设置单个PHP进程可以使用的最大系统内存。

该设置默认值为128M,可以适合大多数中小型PHP应用程序。但是,如果您使用的是微型 PHP 应用程序,则可以降低该值以节省系统资源。相反,如果您使用的是微型 PHP 应用程序,则可以针对内存密集型 PHP 应用程序增加该值。该值的大小由可用的系统内存决定。确定分配给 PHP 的值是一门艺术。在决定分配给 PHP 多少内存以及能够承受多少个 PHP-FPM 进程时,可以根据以下维度信息进行估算:

  1. PHP 可以分配多少内存?以2G内存的VPS为例。该设备还可以运行MySQL、Nginx等其他进程,因此为PHP留512M是合适的。
  2. 每个 PHP 进程平均消耗多少内存?要监控进程的内存使用情况,可以使用命令行命令top或在PHP脚本中调用函数memory_get_peak_usage()。无论采用哪种方法,都必须多次使用。运行相同的脚本并获取平均内存消耗。
  3. 可以承受多少个 PHP-FPM 进程?假设我给PHP分配了512M内存,每个PHP进程平均消耗15M内存,那么我可以负担34个PHP-FPM进程。

系统资源是否足够?最后,您需要确认有足够的系统资源来运行 PHP 应用程序并处理预期的流量。有关更详细的 PHP 配置信息,请参阅 php-fpm.config 配置文件。

; Time limit for child processes to wait for a reaction on signals from master.
; Available units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
;process_control_timeout = 0

; The maximum number of processes FPM will fork. This has been designed to control
; the global number of processes when using dynamic PM within a lot of pools.
; Use it with caution.
; Note: A value of 0 indicates no limit
; Default Value: 0
; process.max = 128

; Specify the nice(2) priority to apply to the master process (only if set)
; The value can vary from -19 (highest priority) to 20 (lowest priority)
; Note: - It will only work if the FPM master process is launched as root
;       - The pool process will inherit the master process priority
;         unless specified otherwise
; Default Value: no set
; process.priority = -19

; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging.
; Default Value: yes
daemonize = no

php-fpm 有固定进程数、按需进程数和完全动态进程数三种运行模式。

  1. 按需设置进程数,部分进程默认重置。如果输入大小太大,则会动态创建一些新进程。请求完成后,新创建的进程将被销毁。
  2. 提高工序数量。默认情况下,某些进程是固定的。如果没有足够的进程,新的请求将等待,直到其他进程完成处理为止。
  3. 完全动态的进程计数意味着它完全由请求数量控制。为每个请求创建一个进程,并在处理后销毁。

启用 Zend OPcache 性能加速

确定要分配的内存量后,您可以配置 PHP Zend OPcache 扩展。 OPcache主要是将部分代码解析为字节码,因此后续请求不需要重复解析和编译那部分代码。减少编译和解析过程还可以提高PHP处理速度。

PHP5.5.0+内置了此扩展。这里是必要的配置信息:

opcache.memory_conclusion = 64:为操作码缓存分配的内存(单位为MB),分配的内存容量应该可以存储应用程序中PHP脚本编译的所有操作码。根据应用程序的大小,可以将该值设置为不同的大小。

opcache.interned_strings_buffer = 16:用于存储持久化字符串的内存容量(单位为MB)。什么是常驻字符串?在幕后,PHP 解释器会查找同一字符串的多个实例并将该字符串存储在内存中。如果再次使用相同的字符串,PHP 解释器将使用游标。这是为了节省内存。默认情况下,PHP 驻留字符串是在每个 PHP 进程中分配的。此设置允许 PHP-FPM 进程池将所有进程驻留字符串存储在共享缓冲区中,以便 PHP-FPM 进程池可以处理它们。常驻字符串在多个进程之间引用,这样可以节省更多内存。

opcache.max_accelerated_files = 4000:操作码缓存中可以存储的 PHP 脚本的最大数量。该值的范围在2000到100000之间。该值必须大于PHP应用程序中的文件数。

opcache.validate_timestamps = 1:如果此设置设置为1,PHP将在一定时间后检查PHP脚本的内容是否发生更改。检查间隔由 opcache.revalidate_freq 设置设置。如果此设置的值为 0,PHP 将不会检查 PHP 脚本的内容是否已更改,我们必须自己刷新缓存的操作码。开发环境建议设置为1,生产环境建议设置为0。

opcache.revalidate_freq = 0:设置检查PHP脚本内容是否更改的频率(以秒为单位)。 0秒设置的含义是,只有当opcache.validate_timestamps设置为1时,PHP文件才会在每次请求时重新验证,这样在开发环境中PHP文件每次都会重新验证,但在生产环境中则不会。

opcache.fast_shutdown = 1:此设置允许操作码使用更快的关闭步骤,将对象销毁和释放内存留给 Zend Engine 内存管理器。

上传文件

如果您的应用允许文件上传,最好设置可上传的最大文件大小。另外,最好设置一次可以上传的最大文件数:

file_uploads = 1
upload_max_filesize = 10M
max_file_uploads = 3

默认情况下,PHP允许一次请求上传20个文件,最大可以上传的文件为2MB。这里我把它设置为一。一个应用程序最多只能上传 3 个文件,每个文件最大为 10 MB。该值不要设置太大,否则会超时。

注意:如果需要上传大文件,需要对Web服务器配置进行相应调整。除了php.ini文件中的设置外,还需要调整Nginx虚拟主机配置中的设置client_max_body_size

另外,如果您要上传特别大的文件,我建议使用Webuploader的专用上传组件。前端切碎大文件,后端PHP合并碎片数据来恢复文件。关于WebUploader的信息,请参见本站文章:强大的文件上传组件-WebUploader。

执行时间

max_execution_time 用于指定单个 PHP 进程在终止之前可以运行的最长时间。默认设置为 30 秒,建议设置为 5 秒:

max_execution_time = 5

在 PHP 脚本中,您可以调用函数 set_limit_time() 来覆盖此设置。

假设我们要创建一个报告并将结果转换为 PDF 文件。该任务可能需要 10 分钟才能完成,我们当然不希望 PHP 请求等待 10 分钟。我们应该编写一个单独的 PHP 文件并让它等待 10 分钟。当在单独的后台进程中运行时,Web 应用程序只需几毫秒即可生成单独的后台进程并返回 HTTP 响应。

事实上,当我们运行需要很长时间才能完成的任务时,我们通常会使用后台进程。例如,我们可以使用 PHP swoole 扩展来生成报告并发送需要很长时间的部分电子邮件。

会话处理

PHP 默认将会话生成的信息(例如所谓的会话信息)保存到磁盘。创建和读取会话时,I/O 操作在磁盘上执行。磁盘的读写实际上是一个比较耗时的活动。并且session不方便处理分布式应用的会话机制。建议放在Redis、memcached等内存服务中,读写速度快,可以通过分布式会话机制处理。

以下示例存储缓存信息,例如会话。

session.save_handler = "memcached"
session.save_path = "服务地址:端口号"

缓冲区

如果网络以更少的块发送更多的数据,而不是以更多的块(即更少的块)发送更少的数据,那么网络将会更加高效。以片段形式向访问者的浏览器传送内容可以减少 HTTP 请求的总数。

这就是我们希望 PHP 缓冲输出的原因。默认情况下,PHP 启用输出缓冲功能。 PHP 在将内容发送到 Web 服务器之前缓冲 4096 字节的输出。推荐配置如下:

output_buffering = 4096
implicit_flush = false

如果要更改输出缓冲区大小,请确保使用 4(32 位系统)或 8(64 位系统)的倍数的值。

安全设置

open_basedir:使用open_basedir选项可以控制PHP脚本仅访问指定的目录。这样可以防止PHP脚本访问不应该访问的文件,一定程度上限制了对phpshell的损害。通常我们可以设置为只访问网站目录:

open_basedir = /data/www

disable_functions:一般情况下,我们要禁用系统功能,禁用所有文件和目录操作,例如:

disable_functions = '.....'

expose_php = Off:设置此选项如果为 false,则标头中不输出 PHP 版本信息。

display_errors = Off:在生产环境中我们应该禁用错误消息。如果是本地开发环境,可以设置为on。

log_errors = On:关闭display_errors后,建议记录错误信息,以便更容易查找服务器运行的原因。

error_log:指定PHP错误日志保存的目录。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门