PHP项目中,尤为是在高并发大流量的场景中,如何提高PHP的响应时间,是一项十分重要的工做。php
而Opcache又是优化PHP性能不可缺失的组件,尤为是应用了PHP框架的项目中,做用更是明显。面试
在理解 OPCache 功能以前,咱们有必要先理解PHP-FPM + Nginx 的工做机制,以及PHP脚本解释执行的机制。json
请求从Web浏览器到Nginx,再到PHP处理完成,一共要经历以下五个步骤:浏览器
第一步:启动服务缓存
第二步:Request => Nginx服务器
第三步:Nginx => PHP-FPM架构
第四步:PHP-FPM Master => Worker并发
第五步:PHP-FPM Worker => Master => Nginx框架
了解了PHP + Nginx 总体的处理流程后,咱们接下来看一下PHP脚本具体执行流程,首先咱们看一个实例:socket
<?php if (!empty($_POST)) { echo "Response Body POST: ", json_encode($_POST), "\n"; } if (!empty($_GET)) { echo "Response Body GET: ", json_encode($_GET), "\n"; }
咱们分析一下执行过程:
在PHP cli模式下,每次执行PHP脚本,四个步骤都会依次执行一遍;
在PHP-FPM模式下,步骤1)在PHP-FPM启动时执行一次,后续的请求中再也不执行;步骤2)~4)每一个请求都要执行一遍;
其实步骤2)、3)生成的语法树和opcode,同一个PHP脚本每次运行的结果都是同样的,
在PHP-FPM模式下,每次请求都要处理一遍,是对系统资源极大的浪费,那么有没有办法优化呢?
固然有,如:
OPCache 是Zend官方出品的,开放自由的 opcode 缓存扩展,还具备代码优化功能,省去了每次加载和解析 PHP 脚本的开销。
PHP 5.5.0 及后续版本中已经绑定了 OPcache 扩展。
缓存两类内容:
OPCache缓存的机制主要是:将编译好的操做码放入共享内存,提供给其余进程访问。
这里就涉及到内存共享机制,另外全部内存资源操做都有锁的问题,咱们一一解读。
UNIX/Linux 系统提供不少种进程间内存共享的方式:
OPCache 使用了前三个共享内存机制,根据配置或者默认mmap 内存共享模式。
依据PHP字节码缓存的场景,OPCache的内存管理设计很是简单,快速读写,不释放内存,过时数据置为Wasted。
当Wasted内存大于设定值时,自动重启OPCache机制,清空并从新生成缓存。
任何内存资源的操做,都涉及到锁的机制。
共享内存:一个单位时间内,只容许一个进程执行写操做,容许多个进程执行读操做;
写操做同时,不阻止读操做,以致于不多有锁死的状况。
这就引起另一个问题:新代码、大流量场景,进程排队执行缓存opcode操做;重复写入,致使资源浪费。
PHP进阶架构师>>>视频、面试文档免费获取docs.qq.com
OPCache 是官方的Opcode 缓存解决方案,在PHP5.5版本以后,已经打包到PHP源码中一块儿发布。
它将PHP编译产生的字节码以及数据缓存到共享内存中, 在每次请求,从缓存中直接读取编译后的opcode,进行执行。
经过节省脚本的编译过程,提升PHP的运行效率。
若是正在使用APC扩展,作一样的工做,如今强烈推荐OPCache来代替,尤为是PHP7中。
Opcache 会缓存OPCode以及以下内容:
首先咱们须要理解,什么是 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等框架中,会引用注释,因此,是否关闭注释的缓存,须要区别对待。
是缓存,都存在过时,以及更新策略等。
而OPCache的更新策略很是简单,到期数据置为Wasted,达到设定值,清空缓存,重建缓存。
这里须要注意:在高流量的场景下,重建缓存是一件很是耗费资源的事儿。
OPCache 在建立缓存时并不会阻止其余进程读取。
这会致使大量进程反复新建缓存。因此,不要设置OPCache过时时间
每次发布新代码时,都会出现反复新建缓存的状况。如何避免呢?
opcache_compile_file()
进行编译缓存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
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 表示缓存所有文件。默认值0opcache.load_comments
boolean
若是禁用,则即便文件中包含注释,也不会加载这些注释内容。本选项能够和 opcache.save_comments
一块儿使用,以实现按需加载注释内容。opcache.fast_shutdown
boolean 若是启用,则会使用快速中止续发事件。所谓快速中止续发事件是指依赖 Zend 引擎的内存管理模块 一次释放所有请求变量的内存,而不是依次释放每个已分配的内存块。opcache.file_cache
配置二级缓存目录并启用二级缓存。启用二级缓存能够在 SHM 内存满了、服务器重启或者重置 SHM 的时候提升性能。默认值为空字符串 ""
,表示禁用基于文件的缓存。opcache.file_cache_only
boolean
启用或禁用在共享内存中的 opcode 缓存。opcache.file_cache_consistency_checks
boolean
当从文件缓存中加载脚本的时候,是否对文件的校验和进行验证。opcache.file_cache_fallback
boolean
在 Windows 平台上,当一个进程没法附加到共享内存的时候, 使用基于文件的缓存,也即:opcache.file_cache_only=1
。须要显示的启用文件缓存。以上内容但愿帮助到你们