使用Rancher在K8S上部署高性能PHP应用程序的教程


Posted in PHP onJuly 10, 2020

介 绍

PHP是网络上最流行的编程语言之一,许多被广泛使用的内容管理系统都使用它开发,如WordPress和Drupal,并为现代服务器端框架(如Laravel和Symfony)提供核心代码。

尽管PHP很受欢迎,但是其缓慢和难以维护也是众所周知的。近几年这两个毛病已经没有那么严重了,但是高性能的PHP应用程序依然会需要两个功能:OPcache和PHP FastCGI进程管理器(PHP-FPM)。

在本文中,你将了解到在Kubernetes上如何使用自定义OPcache和PHP-FPM配置部署一个PHP应用程序以提高其性能。你将使用Rancher来部署一个PHP应用程序,该应用程序使用自定义环境变量来动态配置OPcache和PHP-FPM。我们将展示如何在你的Docker镜像中构建PHP-FPM配置选项并在容器中使用环境变量调整它们。

在PHP中的性能

首先,了解PHP应用程序中如何处理网络请求将对本文接下来的内容很有帮助。

PHP通常运行在web服务器旁边,处理请求并将它们发送到PHP应用程序中。你可以使用PHP-FPM或mod_PHP来运行你的应用程序,但在本文中我们将使用PHP-FPM,因为其性能优势并且NGINX是最常与PHP-FPM一起使用的web服务器。

使用Rancher在K8S上部署高性能PHP应用程序的教程

OPcache介绍

OPcache通过在首次调用脚本时将脚本存储在内存中来加速PHP应用程序。进而,随后的请求将从内存而不是文件系统加载,这可以使你的速度提高74%。

OPcache提供了一些设置,你可以调整这些设置来提高应用程序的性能和可靠性。在本篇教程中,你将了解到如何设置一个PHP Docker镜像,该镜像可以调整OPcache的内存限制、缓存文件数量以及重新验证缓存频率。

PHP-FPM介绍

PHP-FPM(FastCGI进程管理器)会启动一个或多个进程以运行你的PHP应用程序。与mod_PHP(将PHP捆绑为Apache模块)不同,PHP-FPM使你可以精确控制服务器(或容器)运行的进程数量,以及它们应该如何启动和停止。

找到一个理想的PHP-FPM配置高度依赖于你的应用程序以及它所服务的请求数量和容器中的内存和CPU限制。我推荐你阅读Hayden James关于这个主题的文章(链接已放在文末)并且在负载测试环境下测试几种不同的配置。

在K8S上部署一个PHP应用程序

前期准备

在你进行本篇教程之前,你需要做好以下准备:

  • 在你本地机器上安装好的Docker
  • Docker Hub或其他Docker镜像仓库上的账号
  • Rancher部署(如果你还没部署,可以按照Quick start进行)
  • 通过Rancher管理的Kubernetes集群

在本教程中使用的所有代码都可以在Github中获取,或者你可以按照以下步骤从头开始构建应用程序。

PHP应用程序

你将要使用的应用程序是一个显示当前日期的PHP文件。创建一个新文件并将其命名为index.php

<?php
echo 'The current date is ' . date('F jS, Y');

创建Dockerfile和配置文件

在Docker Hub上,你可以获得很多PHP Docker镜像,但它们都没有提供使用环境变量来修改OPcache或PHP-FPM配置的简便方法。使用环境变量的优势在于,您无需每次要调整PHP-FPM或OPcache设置时都需要重建PHP映像。这可以让你快速调整你的应用程序以提升性能。

首先,创建一个名为opcache.ini的新文件。你将复制该文件到PHP镜像中并在Dockerfile中为每个环境变量添加默认值。

# See https://www.php.net/manual/en/opcache.configuration.php for all available configuration options.
[opcache]
opcache.enable=${PHP_OPCACHE_ENABLE}
opcache.memory_consumption=${PHP_OPCACHE_MEMORY_CONSUMPTION}
opcache.max_accelerated_files=${PHP_OPCACHE_MAX_ACCELERATED_FILES}
opcache.revalidate_freq=${PHP_OPCACHE_REVALIDATE_FREQUENCY}
opcache.validate_timestamps=${PHP_OPCACHE_VALIDATE_TIMESTAMPS}

接下来,创建另一个名为www.conf的新文件。该文件将存储PHP-FPM配置选项,你可以通过环境变量对其进行更新:

; See https://www.php.net/manual/en/install.fpm.configuration.php for all available configuration options

; Required user, group, and port options
[www]
user = www-data
group = www-data
listen = 127.0.0.1:9000

; Process manager options
pm = ${PHP_FPM_PM}
pm.max_children = ${PHP_FPM_MAX_CHILDREN}
pm.start_servers = ${PHP_FPM_START_SERVERS}
pm.min_spare_servers = ${PHP_FPM_MIN_SPARE_SERVERS}
pm.max_spare_servers = ${PHP_FPM_MAX_SPARE_SERVERS}
pm.max_requests = ${PHP_FPM_MAX_REQUESTS}

你需要复制这些文件到你的Docker镜像中并且设置默认的环境变量值,因此请在项目的根目录中创建一个新的Dockerfile。添加以下步骤:

FROM php:7.4-fpm

# OPcache defaults
ENV PHP_OPCACHE_ENABLE="1"
ENV PHP_OPCACHE_MEMORY_CONSUMPTION="128"
ENV PHP_OPCACHE_MAX_ACCELERATED_FILES="10000"
ENV PHP_OPCACHE_REVALIDATE_FREQUENCY="0"
ENV PHP_OPCACHE_VALIDATE_TIMESTAMPS="0"

# Install opcache and add the configuration file
RUN docker-php-ext-install opcache
ADD opcache.ini "$PHP_INI_DIR/conf.d/opcache.ini"

# PHP-FPM defaults
ENV PHP_FPM_PM="dynamic"
ENV PHP_FPM_MAX_CHILDREN="5"
ENV PHP_FPM_START_SERVERS="2"
ENV PHP_FPM_MIN_SPARE_SERVERS="1"
ENV PHP_FPM_MAX_SPARE_SERVERS="2"
ENV PHP_FPM_MAX_REQUESTS="1000"

# Copy the PHP-FPM configuration file
COPY ./www.conf /usr/local/etc/php-fpm.d/www.conf

# Copy the PHP application file
COPY ./index.php /var/www/public/index.php
RUN chown -R www-data:www-data /var/www/public

Dockerfile将OPCache配置、PHP-FPM配置以及PHP应用程序文件复制到镜像中,并确保包含PHP代码的var/www/public目录为PHP-FPM用户所有。ENV 声明设置了默认的PHP_OPCACHE_...PHP_FPM_...环境变量,但你可以在运行这个镜像时随时覆盖它们。这将使实际部署中的性能调整变得更加容易。

构建并推送到DockerHub

至此,你的项目中已经有了一个单文件PHP应用程序、一个OPcache配置文件、一个PHP-FPM配置文件和一个Dockerfile。你现在可以构建你的Docker镜像:

docker build -t <YOUR_USERNAME>/php-fpm .

接下来,将镜像推送到Docker Hub:

docker push <YOUR_USERNAME>/php-fpm

部署一个PHP-FPM工作负载

既然你的自定义PHP-FPM镜像在Docker Hub上已经可以获取,你可以将其作为工作负载的一部分部署在Kubernetes集群上。使用Rancher UI,创建一个新的deployment,将其命名为php-fpm,并使用<YOUR_USERNAME>/php-fpm作为Docker镜像。你可以修改以上Dockerfile中使用的任何PHP_OPCACHE _...PHP_FPM _...环境变量。

使用Rancher在K8S上部署高性能PHP应用程序的教程

在设置Nginx工作负载以服务于PHP-FPM deployment之前,请检查你的PHP-FPM和OPcache设置是否已正确添加到容器中。在Rancher UI中,单击PHP deployment旁边的三个点,然后单击“ Execute Shell”:

使用Rancher在K8S上部署高性能PHP应用程序的教程

要检查OPcache模块是否已启用,请键入php-fpm -i。这将输出整个PHP .ini配置。浏览一下OPcache上的部分,你应该会看到类似以下内容(更改的任何值都会反映出来):

...
opcache.blacklist_filename => no value => no value
opcache.consistency_checks => 0 => 0
opcache.dups_fix => Off => Off
opcache.enable => On => On
opcache.enable_cli => Off => Off
opcache.enable_file_override => Off => Off
opcache.error_log => no value => no value
opcache.file_cache => no value => no value
opcache.file_cache_consistency_checks => 1 => 1
opcache.file_cache_only => 0 => 0
opcache.file_update_protection => 2 => 2
opcache.force_restart_timeout => 180 => 180
opcache.huge_code_pages => Off => Off
opcache.interned_strings_buffer => 8 => 8
opcache.lockfile_path => /tmp => /tmp
opcache.log_verbosity_level => 1 => 1
opcache.max_accelerated_files => 10000 => 10000
opcache.max_file_size => 0 => 0
opcache.max_wasted_percentage => 5 => 5
opcache.memory_consumption => 256 => 256
opcache.opt_debug_level => 0 => 0
opcache.optimization_level => 0x7FFEBFFF => 0x7FFEBFFF
opcache.preferred_memory_model => no value => no value
opcache.preload => no value => no value
opcache.preload_user => no value => no value
opcache.protect_memory => 0 => 0
opcache.restrict_api => no value => no value
opcache.revalidate_freq => 0 => 0
opcache.revalidate_path => Off => Off
opcache.save_comments => 1 => 1
opcache.use_cwd => On => On
opcache.validate_permission => Off => Off
opcache.validate_root => Off => Off
opcache.validate_timestamps => Off => Off
...

每当你重新部署PHP-FPM工作负载时,PHP-FPM都会重新启动并重置OPcache,因此,当你在Kubernetes上运行PHP-FPM时,你通常不必担心重置OPcache。如果确实要手动刷新缓存,最简单的方法是从Rancher UI重新部署工作负载。

为了确保PHP-FPM配置更改可以生效,请在shell中键入php-fpm -tt。你应该看到所有PHP-FPM选项的列表,包括进程管理器更新的部分(该管理器添加到www.conf文件并使用环境变量进行设置):

NOTICE: pm = dynamic
NOTICE: pm.max_children = 10
NOTICE: pm.start_servers = 2
NOTICE: pm.min_spare_servers = 1
NOTICE: pm.max_spare_servers = 2
NOTICE: pm.process_idle_timeout = 10
NOTICE: pm.max_requests = 1000

部署Nginx工作负载

现在,你有一个PHP-FPM工作负载,但是没有Web服务器可以访问它。你可以使用许多NGINX Docker镜像来为你的PHP应用程序提供服务,但是我通常使用这个NGINX镜像(https://www.shiphp.com/blog/2018/nginx-php-fpm-with-env ),它允许你通过使用环境变量将一个镜像用于任意数量的PHP-FPM工作负载。

在Rancher UI中创建新的工作负载,该负载与PHP-FPM工作负载在相同的集群上。将其命名为nginx,使用Docker镜像shiphp / nginx-env,将容器上的端口80映射到集群上的开放端口,并添加环境变量NGINX_HOST = php-fpm

使用Rancher在K8S上部署高性能PHP应用程序的教程

如果你把PHP-FPM工作负载命名为php-fpm以外的名字,或者你想为第二个工作负载提供服务,你可以使用NGINX_HOST环境变量来连接它,这也允许你在同一个集群上运行多个PHP-FPM和Nginx工作负载。这也允许你在同一个集群上运行多个PHP-FPM和Nginx工作负载。

一旦你的Nginx工作负载可用,点击它所在的端口链接,打开Web应用程序。你应该看到你的PHP脚本生成的当前日期。

使用Rancher在K8S上部署高性能PHP应用程序的教程

结 论

现在,你已经将PHP-FPM工作负载部署到了Kubernetes集群中,你可以开始真正的性能调优工作了。幸运的是,现在更新 PHP-FPM 和 OPcache设置就像更改环境变量和重新部署 Workload 一样简单。这将允许你尝试新的设置,并比重新构建镜像更快获得反馈。

从Web应用程序中获得最佳性能是一个反复的过程,但希望本教程中的Kubernetes部署能帮助你构建更高性能的PHP应用程序。

参考链接:

PHP性能提升:
https://gbksoft.com/blog/php-5-vs-php-7-performance-comparison/

PHP-FPM性能优势:
https://www.cloudways.com/blog/php-fpm-on-cloud/

NGINX
http://nginx.org/en/

OPcache配置设置:
https://www.php.net/manual/en/opcache.configuration.php

提升性能以及你的OPcache应用程序可靠性:
https://tideways.com/profiler/blog/fine-tune-your-opcache-configuration-to-avoid-caching-suprises

Hayden James的PHP-FPM调整文章:
https://haydenjames.io/php-fpm-tuning-using-pm-static-max-performance/

PHP-FPM配置测试:
https://speakerdeck.com/erictendian/performance-testing-and-optimization-with-laravel-and-lumen

到此这篇关于使用Rancher在K8S上部署高性能PHP应用程序的文章就介绍到这了,更多相关Rancher部署K8s PHP应用程序内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

PHP 相关文章推荐
一个ORACLE分页程序,挺实用的.
Oct 09 PHP
php 自写函数代码 获取关键字 去超链接
Feb 08 PHP
基于PHP读取TXT文件向数据库导入海量数据的方法
Apr 23 PHP
PHP设计模式之责任链模式的深入解析
Jun 13 PHP
php calender(日历)二个版本代码示例(解决2038问题)
Dec 24 PHP
php导出csv格式数据并将数字转换成文本的思路以及代码分享
Jun 05 PHP
PHP与MYSQL中UTF8 中文排序示例代码
Oct 23 PHP
php实现数组按指定KEY排序的方法
Mar 30 PHP
Yii2框架可逆加密简单实现方法
Aug 25 PHP
PHP实现一个多功能购物网站的案例
Sep 13 PHP
微信公众号之主动给用户发送消息功能
Jun 22 PHP
PHP对接阿里云虚拟号的实现(号码隐私保护)
Apr 06 PHP
PHP实现简易用户登录系统
Jul 10 #PHP
PHP二维数组分页2种实现方法解析
Jul 09 #PHP
详解阿里云视频直播PHP-SDK接入教程
Jul 09 #PHP
PHP利用curl发送HTTP请求的实例代码
Jul 09 #PHP
PHP使用POP3读取邮箱接收邮件的示例代码
Jul 08 #PHP
phpmyadmin在宝塔面板里进不去的解决方案
Jul 06 #PHP
详解PHP中的8个魔术常量
Jul 06 #PHP
You might like
新版PHP将向Java靠拢
2006/10/09 PHP
php指定函数参数默认值示例代码
2013/12/04 PHP
带密匙的php加密解密示例分享
2014/01/29 PHP
PHP基于GD库的图像处理方法小结
2016/09/27 PHP
详谈symfony window下的安装 安装时候出现的问题以及解决方法
2017/09/28 PHP
Yii框架函数简单用法分析
2019/09/09 PHP
总结一些js自定义的函数
2006/08/05 Javascript
解决FLASH需要点击激活的代码
2006/12/20 Javascript
js控制不同的时间段显示不同的css样式的实例代码
2013/11/04 Javascript
javascript解析json数据的3种方式
2014/05/08 Javascript
Javascript基础教程之变量
2015/01/18 Javascript
Jquery实现弹性滑块滑动选择数值插件
2015/08/08 Javascript
jquery选择器简述
2015/08/31 Javascript
JQuery实现网页右侧随动广告特效
2016/01/17 Javascript
JS 根据子网掩码,网关计算出所有IP地址范围示例
2020/04/23 Javascript
基于javascript实现按圆形排列DIV元素(三)
2016/12/02 Javascript
原生Aajax 和jQuery Ajax 写法个人总结
2017/03/24 jQuery
AngularJS实现表单元素值绑定操作示例
2017/10/11 Javascript
Node.JS段点续传:Nginx配置文件分段下载功能的实现方法
2018/03/12 Javascript
模块化react-router配置方法详解
2019/06/03 Javascript
NodeJS实现一个聊天室功能
2019/11/25 NodeJs
Vue.js原理分析之nextTick实现详解
2020/09/07 Javascript
javascript中layim之查找好友查找群组
2021/02/06 Javascript
[05:24]TI9采访——教练
2019/08/24 DOTA
python自动化测试实例解析
2014/09/28 Python
python实现简单socket通信的方法
2016/04/19 Python
用matplotlib画等高线图详解
2017/12/14 Python
Python 判断 有向图 是否有环的实例讲解
2018/02/01 Python
tensorflow 获取模型所有参数总和数量的方法
2018/06/14 Python
Python多进程池 multiprocessing Pool用法示例
2018/09/07 Python
python中使用zip函数出现错误的原因
2018/09/28 Python
Python设计模式之迭代器模式原理与用法实例分析
2019/01/10 Python
selenium+python自动化测试之使用webdriver操作浏览器的方法
2019/01/23 Python
django 多对多表的创建和插入代码实现
2019/09/09 Python
在Sublime Editor中配置Python环境的详细教程
2020/05/03 Python
英国领先的男装设计师服装购物网站:Mainline Menswear
2018/02/04 全球购物