背景
由于准备采用Yii2开发,必须将php环境升级到5.4+,而公司目前的服务器是win2003,PHP从5.5开始,就不支持XP和2003了,因此目前最高的5.6版本就不指望了。
当前配置
Windows 2003 Server(32位)
Apache2.2 + FCGI 2.3.6
PHP 5.3.6 nts + WinCache
第一次升级
PHP 5.4.45 nts + WinCache
升级后本地测试一切正常,放到服务器上后,问题开始出现了,日志里不定期(1个小时或几个小时)出现一些错误,出错的现象是:web服务无法正常返回,php-cgi.exe的个数有可能为0。大约几分钟后,能自动恢复。日志错误大概是以下几种:
mod_fcgid: read timeout from pipe
Premature end of script headers: index.php
管道已结束。 : mod_fcgid: get overlap result error
PHP Fatal error: WINCACHE: lock_readlock: acquired abandoned mutex FILE_CHANGE_NOTIFY
分析&尝试
怀疑是fcgi的问题,调整了一系列参数,例如:PHP_FCGI_MAX_REQUESTS,FcgidIOTimeout,问题依然存在
找了几个fcgi的其它两个版本,问题依然存在
实在没招了,打算放弃fcgi模式,采用isapi模式
第二次:isapi模式
由于isapi模式需要线程安全(ts)版本,因此需要重新下载所有相关文件的ts版本。
生成环境需要考虑性能,没有opcode缓存是不能容忍的,那么问题来了,以前使用的WinCache并没有ts版本!这可以理解,WinCache毕竟是Microsoft为了IIS更好的支持PHP而开发的,而IIS就是采用的FastCGI与PHP连接,不支持ts实属正常。
于是,我换用APC,开发机是win7,一切正常,放到win2003服务器上,发现apc模块无法加载。于是网上一阵狂搜,终于找到一个win2003上能用的版本(感谢好心人!神奇的是,这个版本在win7上又不能加载,这也无所谓了)
一切就绪,放上服务器开跑。非常郁闷,虽然上文中的报错信息不出现了,但是出现了更严重的问题:跑了一段时间后,Apache崩溃了。在windows中,Apache运行起来会有两个httpd.exe存在,崩溃了就只有一个httpd.exe在运行,而我的服务监控脚本还检测不到Apache服务已经歇菜了,这样,页面完全无法访问,情况更坏了!
再思考
都是跑一段时间后再出错,让我意识到应该是某个模块不稳定造成的。现在已经放弃了fcgi依然有问题,并且,之前使用PHP5.3.6 nts时,并无稳定性问题,fcgi模块的稳定性嫌疑可以暂时排除。Apache也是用的以前的版本,现在只剩下PHP+APC了,因此,我做了一个尝试,禁用APC,效果居然出奇的好!系统一直非常稳定,那么问题基本定位了,不稳定是由于opcode缓存模块造成的,换成PHP5.4.45后,无论是wincache,还是apc,均是如此。
寻找解决方案
问题定位之后就比较容易了,既然目前的opcode缓存都有问题,我就试试其他的。先后尝试了opcache、eAccelerator、xcache,经常碰到load失败的问题,最后xcache3.2.0满足需求,通过了线上试跑。
接下来,将整个方案换回 fcgi 模式,服务同样很稳定,这下心里终于踏实了。
xcache
备忘一下xcache的配置
xcache.size = 32M
xcache.readonly_protection = On
说明:
size属性缺省是0,这意味着xcache并没有开启!
readonly_protection 属性是写保护,开始能增加稳定性,但会带来一点性能损失。
遗留的问题
在 fcgi 模式下,xcache的缓存是针对单个php-cgi.exe的,这回导致目录中的同一个文件会被不同的php-cgi.exe解析并缓存。关于这一点,xcache文档上有说明,并提供了解决方案,我按照说明配置了 PHP_FCGI_CHILDREN 参数,并没有改善。