PHP项目中,尤其是在高并发大流量的场景中,如何提升PHP的响应时间,是一项十分重要的工作。而Opcache又是优化PHP性能不可缺失的组件,尤其是应用了PHP框架的项目中,作用更是明显。
1. 概述在理解 OPCache 功能之前,我们有必要先理解PHP-FPM + Nginx 的工作机制,以及PHP脚本解释执行的机制。 1.1 PHP-FPM + Nginx 的工作机制请求从Web浏览器到Nginx,再到PHP处理完成,一共要经历如下五个步骤:
第一步:启动服务
  • 启动PHP-FPM。PHP-FPM 支持两种通信模式:TCP socket和Unix socket;

  • PHP-FPM 会启动两种类型的进程:Master 进程 和 Worker 进程,前者负责监控端口、分配任务、管理Worker进程;后者就是PHP的cgi程序,负责解释编译执行PHP脚本。

  • 启动Nginx。首先会载入 ngx_http_fastcgi_module 模块,初始化FastCGI执行环境,实现FastCGI协议请求代理

  • 这里要注意:fastcgi的worker进程(cgi进程),是由PHP-FPM来管理,不是Nginx。Nginx只是代理

第二步:Request => Nginx
  • Nginx 接收请求,并基于location配置,选择一个合适handler

  • 这里就是代理PHP的 handler

第三步:Nginx => PHP-FPM
  • Nginx 把请求翻译成fastcgi请求

  • 通过TCP socket/Unix Socket 发送给PHP-FPM 的master进程

第四步:PHP-FPM Master => Worker
  • PHP-FPM master 进程接收到请求

  • 分配Worker进程执行PHP脚本,如果没有空闲的Worker,返回502错误

  • Worker(php-cgi)进程执行PHP脚本,如果超时,返回504错误

  • 处理结束,返回结果

第五步:PHP-FPM Worker => Master => Nginx
  • PHP-FPM Worker 进程返回处理结果,并关闭连接,等待下一个请求

  • PHP-FPM Master 进程通过Socket 返回处理结果

  • Nginx Handler顺序将每一个响应buffer发送给第一个filter → 第二个 → 以此类推 → 最终响应发送给客户端

1.2 PHP脚本解释执行的机制了解了PHP + Nginx 整体的处理流程后,我们接下来看一下PHP脚本具体执行流程,首先我们看一个实例:
<?phpif (!empty($_POST)) {    echo "Response Body POST: ", json_encode($_POST), "\n";}
if (!empty($_GET)) { echo "Response Body GET: ", json_encode($_GET), "\n";}

我们分析一下执行过程:1.php初始化执行环节,启动Zend引擎,加载注册的扩展模块2.初始化后读取脚本文件,Zend引擎对脚本文件进行词法分析(lex),语法分析(bison),生成语法树3.Zend 引擎编译语法树,生成opcode,4.Zend 引擎执行opcode,返回执行结果
在PHP cli模式下,每次执行PHP脚本,四个步骤都会依次执行一遍;在PHP-FPM模式下,步骤1)在PHP-FPM启动时执行一次,后续的请求中不再执行;步骤2)~4)每个请求都要执行一遍;其实步骤2)、3)生成的语法树和opcode,同一个PHP脚本每次运行的结果都是一样的,在PHP-FPM模式下,每次请求都要处理一遍,是对系统资源极大的浪费,那么有没有办法优化呢? 当然有,如:
  • OPCache:前身是Zend Optimizer+ ,是 Zend Server 的一个开源组件;官方出品,强力推荐

  • APC:Alternative PHP Cache 是一个开放自由的 PHP opcode 缓存组件,用于缓存、优化 PHP 中间代码;已经不更新了不推荐

  • APCu:是APC的一个分支,共享内存,缓存用户数据,不能缓存opcode,可以配合Opcache 使用

  • eAccelerate:同样是不更新了,不推荐

  • xCache:不再推荐使用了

2. OPCache 介绍
OPCache 是Zend官方出品的,开放自由的 opcode 缓存扩展,还具有代码优化功能,省去了每次加载和解析 PHP 脚本的开销。PHP 5.5.0 及后续版本中已经绑定了 OPcache 扩展。 缓存两类内容:
  • OPCode

  • Interned String,如注释、变量名等


3. OPCache 原理OPCache缓存的机制主要是:将编译好的操作码放入共享内存,提供给其他进程访问。这里就涉及到内存共享机制,另外所有内存资源操作都有锁的问题,我们一一解读。 3.1 共享内存UNIX/Linux 系统提供很多种进程间内存共享的方式:1.System-V shm API: System V共享内存,
  • sysv shm是持久化的,除非被一个进程明确的删除,否则它始终存在于内存里,直到系统关机;

2.mmap API:
  • mmap映射的内存在不是持久化的,如果进程关闭,映射随即失效,除非事先已经映射到了一个文件上

  • 内存映射机制mmap是POSIX标准的系统调用,有匿名映射和文件映射两种

  • mmap的一大优点是把文件映射到进程的地址空间

  • 避免了数据从用户缓冲区到内核page cache缓冲区的复制过程;

  • 当然还有一个优点就是不需要频繁的read/write系统调用

3.POSIX API:System V 的共享内存是过时的, POSIX共享内存提供了使用更简单、设计更合理的API.4.Unix socket API
OPCache 使用了前三个共享内存机制,根据配置或者默认mmap 内存共享模式。依据PHP字节码缓存的场景,OPCache的内存管理设计非常简单,快速读写,不释放内存,过期数据置为Wasted。当Wasted内存大于设定值时,自动重启OPCache机制,清空并重新生成缓存。 3.2 互斥锁任何内存资源的操作,都涉及到锁的机制。共享内存:一个单位时间内,只允许一个进程执行写操作,允许多个进程执行读操作;写操作同时,不阻止读操作,以至于很少有锁死的情况。这就引发另外一个问题:新代码、大流量场景,进程排队执行缓存opcode操作;重复写入,导致资源浪费。
4. OPCache 缓存解读OPCache 是官方的Opcode 缓存解决方案,在PHP5.5版本之后,已经打包到PHP源码中一起发布。它将PHP编译产生的字节码以及数据缓存到共享内存中, 在每次请求,从缓存中直接读取编译后的opcode,进行执行。通过节省脚本的编译过程,提高PHP的运行效率。如果正在使用APC扩展,做同样的工作,现在强烈推荐OPCache来代替,尤其是PHP7中。 4.1 OPCode 缓存Opcache 会缓存OPCode以及如下内容:
  • PHP脚本涉及到的函数

  • PHP脚本中定义的Class

  • PHP脚本文件路径

  • PHP脚本OPArray

  • PHP脚本自身结构/内容

4.2 Interned String 缓存首先我们需要理解,什么是 Interned String?在PHP5.4的时候, 引入了Interned String机制, 用于优化PHP对字符串的存储和处理。尤其是处理大块的字符串,比如PHP doces时,Interned String 可以优化内存。Interned String 缓存的内容包括:变量名称、类名、方法名、字符串、注释等。
在PHP-FPM模式中,Interned String 缓存字符,仅限于Worker 进程内部。而缓存到OPCache中,那么Worker进程之间可以使用 Interned String 缓存的字符串,节省内存。
我们需要注意一个事情,在PHP开发中,一般会有大段的注释,也会被缓存到OPCache中。可以通过php.ini的配置,关闭注释的缓存。但是,像Zend Framework等框架中,会引用注释,所以,是否关闭注释的缓存,需要区别对待。 5. OPCache 更新策略是缓存,都存在过期,以及更新策略等。而OPCache的更新策略非常简单,到期数据置为Wasted,达到设定值,清空缓存,重建缓存。 这里需要注意:在高流量的场景下,重建缓存是一件非常耗费资源的事儿。OPCache 在创建缓存时并不会阻止其他进程读取。这会导致大量进程反复新建缓存。所以,不要设置OPCache过期时间 每次发布新代码时,都会出现反复新建缓存的情况。如何避免呢?
  • 不要在高峰期发布代码,这是任何情况下都要遵守的规则

  • 代码预热,比如使用脚本批量调PHP 访问URL,或者使用OPCache 暴露的API 如opcache_compile_file() 进行编译缓存

6. OPCache 的配置6.1 内存配置
  • opcache.preferred_memory_model="mmap" OPcache 首选的内存模块。如果留空,OPcache 会选择适用的模块, 通常情况下,自动选择就可以满足需求。可选值包括:mmap,shm, posix 以及 win32。

  • opcache.memory_consumption=64 OPcache 的共享内存大小,以兆字节为单位,默认64M

  • opcache.interned_strings_buffer=4 用来存储临时字符串的内存大小,以兆字节为单位,默认4M

  • opcache.max_wasted_percentage=5 浪费内存的上限,以百分比计。如果达到此上限,那么 OPcache 将产生重新启动续发事件。默认5

6.2 允许缓存的文件数量以及大小
  • opcache.max_accelerated_files=2000 OPcache 哈希表中可存储的脚本文件数量上限。真实的取值是在质数集合 { 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987 } 中找到的第一个大于等于设置值的质数。设置值取值范围最小值是 200,最大值在 PHP 5.5.6 之前是 100000,PHP 5.5.6 及之后是 1000000。默认值2000

  • opcache.max_file_size=0 以字节为单位的缓存的文件大小上限。设置为 0 表示缓存全部文件。默认值0

6.3 注释相关的缓存
  • opcache.load_commentsboolean 如果禁用,则即使文件中包含注释,也不会加载这些注释内容。本选项可以和 opcache.save_comments 一起使用,以实现按需加载注释内容。

  • opcache.fast_shutdown boolean 如果启用,则会使用快速停止续发事件。所谓快速停止续发事件是指依赖 Zend 引擎的内存管理模块 一次释放全部请求变量的内存,而不是依次释放每一个已分配的内存块。


6.4 二级缓存的配置
  • opcache.file_cache 配置二级缓存目录并启用二级缓存。启用二级缓存可以在 SHM 内存满了、服务器重启或者重置 SHM 的时候提高性能。默认值为空字符串 "",表示禁用基于文件的缓存。

  • opcache.file_cache_onlyboolean 启用或禁用在共享内存中的 opcode 缓存。

  • opcache.file_cache_consistency_checksboolean 当从文件缓存中加载脚本的时候,是否对文件的校验和进行验证。

  • opcache.file_cache_fallbackboolean 在 Windows 平台上,当一个进程无法附加到共享内存的时候, 使用基于文件的缓存,也即:opcache.file_cache_only=1。需要显示的启用文件缓存。

php之Opcache深入理解的更多相关文章

  1. 转 [PHP] - 性能加速 - 开启Opcache

    原文地址:[PHP] - 性能加速 - 开启Opcache PHP7已经发布了, 作为PHP10年来最大的版本升级, 最大的性能升级, PHP7在多放的测试中都表现出很明显的性能提升  一.开启Opc ...

  2. PHP7添加opcache.so模块

    启动php报错如下: # /usr/local/php7/sbin/php-fpm [-Apr- ::] NOTICE: PHP message: PHP Warning: PHP Startup: ...

  3. zend opcache的最佳设置

    2016-01-21 在网上无意中看到的一篇文章,这哥们非常简洁地谈论了zend opcache的最佳设置,他说他为此花了大量的时间探索zend opcache的每个设置选项的细节,甚至是阅读它的源代 ...

  4. 开启opcache提高性能

    在开启opcache之前,我们先介绍一下编译与解释: 编译器是把源程序的每一条语句都编译成机器语言,并保存成二进制文件,这样运行时计算机可以直接以机器语言来运行此程序,速度很快:而解释器则是只在执行程 ...

  5. PHP安装使用Zend Opcache扩展

    简介 Zend OPCache 的前身是Zend Optimizer + (Zend O+),于 2013年3月中旬改名为 Opcache.其通过 opcode 缓存和优化提供更快的 PHP 执行过程 ...

  6. 【转载】深入理解PHP Opcode缓存原理

    转载地址:深入理解PHP Opcode缓存原理 什么是opcode缓存? 当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode).O ...

  7. php高并发之opcache

    今天工作的时候接触到客户的一台服务器,业务逻辑比较简单 .估算pv在120w左右吧,用的是阿里云2c4g的服务器.一大早就开始卡顿了,登陆服务器后查看负载到了八九十. 之后就想办法调整一下吧.突然想起 ...

  8. php之Opcache

    opcache的原理 1.Opcache是什么? Opcache是一种通过将解析的PHP脚本预编译的字节码(Operate Code)存放在共享内存中来避免每次加载和解析PHP脚本的开销,解析器可以直 ...

  9. php7的Opcache getshell

    OPcache基础 OPcache是一种通过解析的PHP脚本预编译的字节码存放在共享内存中来避免每次加载和解析PHP脚本的开销,解析器可以直接从共享内存读取已经缓存的字节码,从而大大提高了PHP的执行 ...

  10. 深入理解 PHP7 中全新的 zval 容器和引用计数机制

    深入理解 PHP7 中全新的 zval 容器和引用计数机制 最近在查阅 PHP7 垃圾回收的资料的时候,网上的一些代码示例在本地环境下运行时出现了不同的结果,使我一度非常迷惑. 仔细一想不难发现问题所 ...

随机推荐

  1. C#/.NET/.NET Core技术前沿周刊 | 第 3 期(2024年8.26-8.31)

    前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录.追踪C#/.NET/.NET Core领域.生态的每周最新.最实用.最有价值的技术文章.社区动态.优质项目和学习资源等. ...

  2. 呵,老板不过如此,SQL还是得看我

    2018年7月,大三暑假进行时,时间过得飞快,我到这边实习都已经一个月了. 我在没工作之前,我老是觉得生产项目的代码跟我平时自学练的会有很大的区别. 以为生产项目代码啥的都会规范很多,比如在接口上会做 ...

  3. vue-i18n 8.28.2(完成)

    https://kazupon.github.io/vue-i18n/zh/introduction.html 开始 如果使用模块系统 (例如通过 vue-cli),则需要导入 Vue 和 VueI1 ...

  4. 算法学习-Dancing Links X

    Dancing Links X 舞蹈链. 实质为用循环十字链在图上将所有"1"的位置链起来 构造较为巧妙,且极易理解,本题为 DLX 模板(精确覆盖问题) DLX 算法的题目做法一 ...

  5. Git常用命令,分支合并与管理

    Git 自我感觉最大的优点是对版本库和分支的管理 各自的电脑都对项目保存一份版本,分支合并也极其方便. 而且Git的目录操作命令跟Linux一样,使用起来还是非常顺手的. Git详解 Git 常用命令 ...

  6. 墨天轮访谈 | Pika数据库陈磊:云时代下,键值数据库是否会被替代?

    分享嘉宾:陈磊 开源数据库Pika项目PMC核心人员 整理:墨天轮社区 导读 大家好,今天我分享的主题是:KV数据库,云时代的文件存储. 随着AI和机器学习等技术的发展,数据演变为了十分宝贵的资源,数 ...

  7. LINQ 统计字符频率

    var arr = new string[] {"test","zhulongxu","asdfdgd","yangmi" ...

  8. 3. 王道OS-操作系统的运行机制,中断和异常

    1. 高级语言- 编译 - 机器指令 (二进制) 2. 内核态和用户态 :刚开机的时候CPU是内核态,当用户启动某个程序的时候CPU是用户态,如果遇到危险,操作系统会夺回CPU的控制权成为内核态,当危 ...

  9. js的宏任务和微任务有哪些,是怎么执行的 ?

    事件循环有宏任务和微任务: 宏任务所处的队列就是宏任务队列,队列可以有多个,第一个队列只有一个任务就是执行主线程的js代码,剩余队列任务有setTimeout setInterval  :微任务所处的 ...

  10. 手动检查 token 是否过期

    1.在 存储 token 的时候说明登录了 此时 把时间戳记录一下  js-cookies - auth.js // 导入 js-cookie 用于操作 cookies import Cookies ...