基础知识
编程语言的虚拟机是一种可以运行中间语言的程序。中间语言是抽象出的指令集,由原生语言编译而成,作为虚拟机执行阶段的输入。很多语言都实现了自己的虚拟机,比如Java、C#和Lua。PHP语言也有自己的虚拟机,称为Zend虚拟机。
PHP7完成基本的准备工作后,会启动Zend引擎,加载注册的扩展模块,然后读取对应的脚本文件,Zend引擎会对文件进行词法和语法分析,生成抽象语法树,接着抽象语法树被编译成Opcodes,如果开启了Opcache,编译的环节会被跳过从Opcache中直接读取Opcodes进行执行。
PHP7中词法语法分析,生成抽象语法树,然后编译成Opcodes及被执行均由Zend虚拟机完成。这里简要说明一下zend虚拟机的实现原理。
zend虚拟机
Zend虚拟机(称为Zend VM)是PHP语言的核心,承担了语法词法解析、抽象语法树编译以及指令的执行工作。
Zend虚拟机主要分为解释层、中间数据层和执行层,下面给出各层包含的内容,如下所示。

下面解释下各层的作用。
(1)解释层
这一层主要负责把PHP代码进行词法和语法分析,生成对应的抽象语法树;另一个工作就是把抽象语法树进行编译,生成符号表和指令集;
(2)中间数据层
这一层主要包含了虚拟机的核心部分,执行栈的维护,指令集和符号表的存储,而这三个是执行引擎调度执行的基础;
(3)执行层
这一层是执行指令集的引擎,这一层是最终的执行并生成结果,这一层里面实现了大量的底层函数。
缓存操作码(opcode)
Opcode,PHP编译后的中间文件,缓存给用户访问
当客户端请求一个PHP程序时,服务器的PHP引擎会解析该PHP程序,并将其编译为特定的操作码文件,该文件是执行PHP代码后的一种二进制文件表现形式。默认情况下,这个编译好的操作码文件由PHP引擎执行后丢弃;而操作码缓存的原理就是将编译后的操作码保存下来,并放入到共享内存里,以便再下一次调用该PHP页面时重用它,避免了相同代码的重复编译。节省了PHP引擎重复编译的时间,降低了服务器负载,同时减少了CPU和内存的开销.
缓存流程说明:
1 nginx 接受客户端的PHP程序访问请求
2 nginx根据扩展名等过滤规则将PHP程序请求传递给解析PHP的fcgi进程(php-fpm)
3 PHP fpm 进程调用PHP解析器读取站点磁盘上的PHP文件,并加载到内存中
4 PHP解析器将PHP程序编译成opcode文件,然后将opcode缓存起来
5 PHP fpm引擎执行opcode之后,返回数据给nginx,进而返回给客户端
6 nginx收到新的PHP请求时,PHP fpm引擎就会直接读取缓存中的opcode并执行,将结果返回。
1 xcache
2 eaccelerator
3 zendopcache
选择方式:通过自己将平台打好进行压力测试,选择自己最合适的
建议:
1 首选xcache,原因是效率好,快,社区活跃支持更高的版本
2 次选eaccelerator,原因,安装配置简单,加速效果更高,文档资料多,但官方不活跃,仅适合于PHP版本5.4以下的程序
3 再选则zendopcache,原因是PHP官方颜值,发展潜力好,PHP5.5之前可以通过zendopcache软件以插件扩展的方式安装,从PHP5.5版本开始已经整合到PHP软件中,编译时只需要指定相关参数即可
下载xcache软件包
wget http://xcache.lighttpd.net/pub/Releases/1.3.0/xcache-1.3.0.tar.gz
##解压
tar zxvf xcache-1.3.0.tar.gz
cd xcache-1.3.0
/usr/local/php/bin/phpize
./configure --enable-xcache \
--with-php-config=/usr/bin/php-config
# make && make install
安装完成后根据提示进入到/usr/lib64/php/modules目录
cd /usr/lib64/php/modules

可以看到xcache.so文件已经生成
进入到/etc/php.d/目录下配置xcache.ini 文件使扩展插件生效
cd /etc/php.d/
cp mysql.ini xcache.ini
vim xcache.ini

重启php-fpm
systemctl restart php-fpm
访问写好的index.php页面即可看到php已加载xcache插件

或者使用php -v也可以查看

基本配置与加载
cd /etc/php.d/
cp mysql.ini xcache.ini
vim xcache.ini
; Enable mysqlnd extension module
extension=xcache.so
#登录管理界面的用户名和密码,留空则禁用管理界面
[xcache.admin]
xcache.admin.enable_auth = On
xcache.admin.user = "admin"
#MD5加密后的密码,echo -n pass | md5sum
xcache.admin.pass = "e10adc3949ba59abbe56e057f20f883e"
[xcache]
#决定 XCache 如何从系统分配共享内存
xcache.shm_scheme ="mmap"
#所用共享缓存的大小。如果为0,缓存将无法使用
xcache.size=60M
#指定将 cache 切分成多少块, 建议设置为 cpu 数 (cat /proc/cpuinfo |grep -c processor)
xcache.count =1
#只是作为 hash 槽个数的参考值
xcache.slots =8K
#Opcode文件的生存时间。如果将此值设置为0,则将无限期缓存 (int)
xcache.ttl=0
#回收器扫描过期的对象回收内存空间的间隔,0不扫描
xcache.gc_interval =0
#同上, 只是针对变量缓存设置
xcache.var_size=4M
xcache.var_count =1
xcache.var_slots =8K
xcache.var_ttl=0
xcache.var_maxttl=0
xcache.var_gc_interval =300
#启用或禁用测试功能
xcache.test =Off
#如果启用了 ReadonlyProtection, 将会略微降低性能, 但是会提高一定的安全系数,这个选项对于xcache.mmap_path = /dev/zero 无效.
xcache.readonly_protection = On
#用于只读保护的文件路径,这将限制两个 php 进程组共享同一个 /tmp/xcache 目录, 指定为 /dev/zero 时无效
xcache.mmap_path ="/tmp/xcache/"
#在遇到故障时,放置核心转储的目录。必须是PHP可写入的目录。保留为空代表禁用.
xcache.coredump_directory =""
在/etc/php.ini文件里根据编译安装后的提示添加如下字段
extension_dir = "/usr/lib64/php/modules/" extension_dir = xcache.so
详细介绍:
xcache.admin.user (String) 管理认证用户名。默认设置"mOo"
xcache.admin.pass (String)管理认证密码。默认设置为"<empty string>"。此值应该是MD5(你的密码)
xcache.admin.enable_auth (String)启用或禁用管理站点的身份验证。默认值"on"
xcache.test (String)启用或禁用测试功能
xcache.coredump_dir (String)在遇到故障时,放置核心转储的目录。必须是PHP可写入的目录。保留为空带表禁用
xcache.cacher (Boolean) 启用或禁用Opcode 缓存。默认开启
xcache.size (int)所有共享缓存的大小。如果为0,缓存将无法使用
xcache.count (int)缓存被分割的“块”数。默认值1
xcache.slots 哈希表提示。数字越大,哈希表内进行的搜索速度就越快。此值越高,所需内存也越多
xcache.ttl (int)Opcode文件的生存时间。0=无限期缓存
xcache.gc_interval (秒) 触发垃圾回收的时间间隔。默认0
xcache.var_size (int)变量大小
xcache.var_count (int)变量个数
xcache.var_slots 可变数据槽设置
xcache.var_ttl (秒)可变数据的生存时间,默认设置0
xcache.var_maxttl (秒)处理变量时最大的生存时间
xcache.var_gc_interval (秒)垃圾回收的生存时间
xcache.readonly_protection (Boolean)启用ReadonlyProtection时可用。
xcache.mmap_path (String)用于只读保护的文件路径。这将限制两个PHP组共享同一个/tmp/cache目录
xcache.optimizer (Boolean)启用或禁用优化 默认禁用
xcache.coverager (Boolean)启用覆盖范围数据集合。
xcache.coveragerdump_directory (String)放置数据集合信息的目录位置。默认使用目录/tmp/pcovis
生成Xcache缓存文件
touch /tmp/xcache
chmod 777 /tmp/xcache
可将tmpfs挂载/tmp/xcache目录下,增加缓存的读写速度。
mount -t tmpfs -o size=64m tmpfs /tmp/xcache
复制相关网页到nginx的主目录下
cd xcache-3.2.0/
cp -a htdocs/ /usr/share/nginx/html
授予相关权限
chown -R nginx.nginx /usr/share/nginx/html
重启php-fpm后访问测试
http://192.168.112.201/htdocs/index.php

输入刚才配置的账号密码

这样就进入到xcache的web界面,可以对缓存信息进行管理
未配置xcache之前的压测结果
[root@vm04 ~]# ab -n 3000 -c 100 192.168.112.201/index.php
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.112.201 (be patient)
Completed 300 requests
Completed 600 requests
Completed 900 requests
Completed 1200 requests
Completed 1500 requests
Completed 1800 requests
Completed 2100 requests
Completed 2400 requests
Completed 2700 requests
Completed 3000 requests
Finished 3000 requests
Server Software: nginx/1.14.2
Server Hostname: 192.168.112.201
Server Port: 80
Document Path: /index.php
Document Length: 73351 bytes
Concurrency Level: 100
Time taken for tests: 26.551 seconds
Complete requests: 3000
Failed requests: 320
(Connect: 0, Receive: 0, Length: 320, Exceptions: 0)
Write errors: 0
Total transferred: 220496635 bytes
HTML transferred: 220052635 bytes
Requests per second: 112.99 [#/sec] (mean)
Time per request: 885.035 [ms] (mean)
Time per request: 8.850 [ms] (mean, across all concurrent requests)
Transfer rate: 8109.99 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 3.1 0 23
Processing: 9 847 1006.0 713 17514
Waiting: 6 787 902.5 682 17508
Total: 9 848 1006.0 714 17514
Percentage of the requests served within a certain time (ms)
50% 714
66% 883
75% 1089
80% 1242
90% 1716
95% 2279
98% 3042
99% 3855
100% 17514 (longest request)
[root@vm04 ~]# ab -n 3000 -c 100 192.168.112.201/index.php
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.112.201 (be patient)
Completed 300 requests
Completed 600 requests
Completed 900 requests
Completed 1200 requests
Completed 1500 requests
Completed 1800 requests
Completed 2100 requests
Completed 2400 requests
Completed 2700 requests
Completed 3000 requests
Finished 3000 requests
Server Software: nginx/1.14.2
Server Hostname: 192.168.112.201
Server Port: 80
Document Path: /index.php
Document Length: 34506 bytes
Concurrency Level: 100
Time taken for tests: 6.001 seconds
Complete requests: 3000
Failed requests: 296
(Connect: 0, Receive: 0, Length: 296, Exceptions: 0)
Write errors: 0
Total transferred: 103961667 bytes
HTML transferred: 103517667 bytes
Requests per second: 499.88 [#/sec] (mean)
Time per request: 200.047 [ms] (mean)
Time per request: 2.000 [ms] (mean, across all concurrent requests)
Transfer rate: 16916.87 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 2 3.6 0 26
Processing: 33 195 115.8 171 1304
Waiting: 2 192 110.0 170 1304
Total: 42 197 116.1 172 1305
Percentage of the requests served within a certain time (ms)
50% 172
66% 182
75% 187
80% 191
90% 227
95% 373
98% 633
99% 778
100% 1305 (longest request)
可以看到未安装xcache时并发数为113,安装xcache之后并发数为499,缓存效果提升了4倍左右。
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
我试过重新启动apache,缓存的页面仍然出现,所以一定有一个文件夹在某个地方。我没有“公共(public)/缓存”,那么我还应该查看哪些其他地方?是否有一个URL标志也可以触发此效果? 最佳答案 您需要触摸一个文件才能清除phusion,例如:touch/webapps/mycook/tmp/restart.txt参见docs 关于ruby-如何在Ubuntu中清除RubyPhusionPassenger的缓存?,我们在StackOverflow上找到一个类似的问题:
我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b
您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除
尝试在我的RoR应用程序中实现计数器缓存列时出现错误Unknownkey(s):counter_cache。我在这个问题中实现了模型关联:Modelassociationquestion这是我的迁移:classAddVideoVotesCountToVideos0Video.reset_column_informationVideo.find(:all).eachdo|p|p.update_attributes:videos_votes_count,p.video_votes.lengthendenddefself.downremove_column:videos,:video_vot
require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame
我有一个使用PDFKit呈现网页的pdf版本的Rails应用程序。我使用Thin作为开发服务器。问题是当我处于开发模式时。当我使用“bundleexecrailss”启动我的服务器并尝试呈现任何PDF时,整个过程会陷入僵局,因为当您呈现PDF时,会向服务器请求一些额外的资源,如图像和css,看起来只有一个线程.如何配置Rails开发服务器以运行多个工作线程?非常感谢。 最佳答案 我找到的最简单的解决方案是unicorn.geminstallunicorn创建一个unicorn.conf:worker_processes3然后使用它: