如何解决PHP,MySQL和通用I / O的性能问题

我有一个基于WordPress的网站在共享主机上运行。 它的响应时间非常不错(大约2s检索HTML页面,5s加载所有资源)。

我打算把它转移到一个专用的虚拟服务器(Ubuntu 12.04 LTS),这应该从理论上改善事情,并使其更加一致,因为它不共享。 然而,我观察到严重的性能下降,页面花费了10秒。

我通过编辑服务器上的/etc/hosts来排除networking问题,并将域映射到127.0.0.1 。 我使用Apache负载testing器来获取HTML,所以JS,CSS和图像都被排除在外。 它仍然需要10秒钟。

我有Zpanel安装在也使用MySQL的服务器上,它的页面速度非常快(1.5s),也是phpMyAdmin。 通过phpMyAdmin直接对wordpress数据库进行一些查询,查询速度也相当快,查询时间在10到30毫秒。

内存也是足够的,只有800Mb被使用的1Gb物理内存可用,所以它似乎也不是交换问题。 我也安装了APC来尝试提高PHP性能,但没有任何影响。

我还应该找什么? 什么可能导致这种性能下降? 因为我在基于云的虚拟服务器上运行,会不会是某种I / O问题?

我希望能够提供与我的提供商的问题,但没有显示实际的数据,从一些诊断,恐怕他只会责怪我的申请。

更新sar输出(每秒)当我做了一个HTTP请求:

 02:31:29 CPU %user %nice %system %iowait %steal %idle 02:31:30 all 0.00 0.00 0.00 0.00 0.00 100.00 02:31:31 all 2.22 0.00 2.22 0.00 0.00 95.56 02:31:32 all 41.67 0.00 6.25 0.00 2.08 50.00 02:31:33 all 86.36 0.00 13.64 0.00 0.00 0.00 02:31:34 all 75.00 0.00 25.00 0.00 0.00 0.00 02:31:35 all 93.18 0.00 6.82 0.00 0.00 0.00 02:31:36 all 90.70 0.00 9.30 0.00 0.00 0.00 02:31:37 all 71.05 0.00 0.00 0.00 0.00 28.95 02:31:38 all 14.89 0.00 10.64 0.00 2.13 72.34 02:31:39 all 2.56 0.00 0.00 0.00 0.00 97.44 02:31:40 all 0.00 0.00 0.00 0.00 0.00 100.00 02:31:41 all 0.00 0.00 0.00 0.00 0.00 100.00 

更新2 josten的build议后。

I / O:

iotop失败, OSError: Netlink error: No such file or directory (2)sar -d也失败, Requested activities not available in file /var/log/sysstat/sa14 。 我认为这是因为这是一个虚拟机,就像iostat也失败了。 难道这就是为什么%iowait报道%iowait的原因总是0%?

CPU负载:

htophtop CPU%的htop实际上是apache2 。 我期待这可能是数据库,但它不是。 当我做一个新的HTTP请求时,它几秒钟就会达到94%。 似乎这是罪魁祸首。

我做了一个strace -f -t和一个总结strace -c -f 。 似乎有很多的lstat电话(57786),2455导致错误。 不知道这是否正常。 除此之外,最重要的电话是wait4 ,我认为是正常的(它只是等待)和munmap 。 下面的前5名

 % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 51.06 0.124742 897 139 6 wait4 14.90 0.036388 1 57786 2455 lstat 9.67 0.023622 13 1857 munmap 7.69 0.018790 37 514 brk 6.70 0.016361 481 34 clone 2.87 0.006999 74 94 12 select 

strace本身减慢了apache的2倍。我正试图了解现在很长的踪迹,看是否有任何指示什么导致CPU秒杀了几秒钟。

对于性能良好的服务器, lstat的典型时间是什么? 我希望收集一些信息,以便我可以以build设性的方式向提供商投诉,如果这是存储访问故障。

更新 fio随机读取testing的输出:

 random-read: (g=0): rw=randread, bs=4K-4K/4K-4K, ioengine=sync, iodepth=1 fio 1.59 Starting 1 process random-read: Laying out IO file(s) (1 file(s) / 128MB) Jobs: 1 (f=1): [r] [100.0% done] [12185K/0K /s] [2975 /0 iops] [eta 00m:00s] random-read: (groupid=0, jobs=1): err= 0: pid=24264 read : io=131072KB, bw=10298KB/s, iops=2574 , runt= 12728msec clat (usec): min=119 , max=162219 , avg=380.34, stdev=957.37 lat (usec): min=119 , max=162219 , avg=380.89, stdev=957.40 bw (KB/s) : min= 7200, max=13424, per=99.89%, avg=10285.72, stdev=1608.68 cpu : usr=2.80%, sys=18.65%, ctx=33511, majf=0, minf=23 IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0% submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% issued r/w/d: total=32768/0/0, short=0/0/0 lat (usec): 250=45.57%, 500=37.17%, 750=3.41%, 1000=7.83% lat (msec): 2=5.67%, 4=0.27%, 10=0.08%, 20=0.01%, 250=0.01% Run status group 0 (all jobs): READ: io=131072KB, aggrb=10297KB/s, minb=10545KB/s, maxb=10545KB/s, mint=12728msec, maxt=12728msec 

我现在唯一的提示是,与其他系统相比, fio输出的CPU线似乎显示出相当多的活动。 我在我的本地Ubuntu机器上运行它,输出结果是:

 cpu : usr=0.19%, sys=0.59%, ctx=32923, majf=0, minf=23 

usr百分比似乎只是我的服务器上报告的一小部分。

更新重新PHP的APC。 是的,它被安装。 从phpinfo输出:

 APC Support enabled Version 3.1.7 APC Debugging Disabled MMAP Support Enabled MMAP File Mask no value Locking type pthread mutex Locks Serialization Support php Revision $Revision: 307215 $ Build Date May 2 2011 19:00:42 

有什么具体的设置我应该检查? 这些是我有的设置(本地值,主值):

 apc.cache_by_default On On apc.canonicalize On On apc.coredump_unmap Off Off apc.enable_cli Off Off apc.enabled On On apc.file_md5 Off Off apc.file_update_protection 2 2 apc.filters no value no value apc.gc_ttl 3600 3600 apc.include_once_override Off Off apc.lazy_classes Off Off apc.lazy_functions Off Off apc.max_file_size 1M 1M apc.mmap_file_mask no value no value apc.num_files_hint 1000 1000 apc.preload_path no value no value apc.report_autofilter Off Off apc.rfc1867 Off Off apc.rfc1867_freq 0 0 apc.rfc1867_name APC_UPLOAD_PROGRESS APC_UPLOAD_PROGRESS apc.rfc1867_prefix upload_ upload_ apc.rfc1867_ttl 3600 3600 apc.serializer default default apc.shm_segments 1 1 apc.shm_size 32M 32M apc.slam_defense On On apc.stat On On apc.stat_ctime Off Off apc.ttl 0 0 apc.use_request_time On On apc.user_entries_hint 4096 4096 apc.user_ttl 0 0 apc.write_lock On On 

更新 apc.shm_size增加到96M。 caching完全计数现在为0,在网站刷新几次之后,caching命中率为96.5%。 APC内存使用率为25.4MB免费。

它似乎已经减less了3秒左右的加载时间,现在下降到大约4至5秒,如果我从服务器本身做一个纯wget没有得到任何图像等仍然比其他托pipe慢两倍,但肯定是一种提升。

我仍然觉得奇怪,为什么当服务器完全空闲(我的开发PC上没有安装APC,并没有这种行为),渲染这些页面的时间太长了。 而那些额外的剩余秒数被浪费的地方仍然很奇怪。

这看起来像我已经看到了Apache花费大量时间编译PHP的其他情况。 你有没有确保操作码caching(如APC)安装? 它将在phpinfo()的输出中显示为已加载的模块,如果有帮助的话。 否则,为了跟踪Apache在mod_php中所做的事情,最好的办法就是XHProf。

除了jbx以外的任何人通过Google到达这里:顺便说一下,其他的答案都很好。 去看看他们。 但是这些答案和jbx对他们的回应,帮助我得出了这个结论。

你必须首先确定问题是什么; 如果是PHP,MySQL,I / O,加载,内存,CPU,内核等, sarlogging系统度量值; 你必须在行为中抓住它。 您可以configurationatop进行会计处理,这肯定有帮助。

确定它是否是I / O

使用诸如iotopatop等工具来查看磁盘使用情况; 这些工具也会告诉你什么导致IO。 一般来说,如果爱荷华州持续超过10%,这可能是问题。

sarlogging磁盘IO; 所以你可以运行sar -d来查看它(查看%util列)。

确定是否是负载

使用诸如htoptopuptime等工具; 再次将其与stream程运行结合起来,找出有关stream程正在执行的更多细节。 请注意,这将报告调度程序的负载; 它不反映CPU使用率。

确定它是否是一个CPU

sar再次来救一天; 你可以用sar -P ALL看到这个信息。 您也可以使用mpstat -P ALL来获取实时数据。 一般来说,如果所有的CPU都处于100%,CPU只是一个问题。 80%以上意味着他们正在被利用(但不一定饱和)。

要确定它是否是内存(VM)

你会想使用vmstat ; vmstat -SM 1并观察swapiosystem列。 显然,大量的交换会影响性能。 还有system部分; 大量的中断也可以做同样的事情。

确定是否是中断

您可以使用vmstat -SM 1 。 不幸的是,如果你的系统没有正常的基线 ,很难判断中断是否是问题。 大量的中断(这是由硬件要求内核动作引起的)将导致系统爬行。 失败的网卡是臭名昭着的。

确定它是否是内核

这是棘手的,但通常需要straceperfsysdig工具。 一个这样的工具是性能perf topstrace与总结( -c )是好的,但它并没有打破它相对于系统资源(所以提供的数据只是猜测); 使用perf top来得出它是内核的结论是理想的。 如果您的机器支持,也可以使用stap (SystemTap)。 我也应该注意, strace会影响性能; 如果系统非常重要,则应该使用sysdig

确定是否是MySQL / PHP

你基本上必须遵循我上面发布的内容(例如可以提供有关什么命令导致高内核时间的信息, iotopatophtop可以提供有关正在使用它们的系统资源的信息); 基本上,您正在使用上述工具来确定是什么导致负载。

一旦你确定它是MySQL

这可能是一个查询,你正在运行(所以你会想在MySQL中使用EXPLAIN查询)。 您还需要确保您的数据库已经过优化,并且正在执行的查询已经过优化。 你还必须确保你使用的表引擎非常适合你正在做的事情(我已经看到很多MyISAM应该是InnoDB的大表)。 如果您确定以上都不是问题,并且仍然怀疑MySQL,则可能需要将数据归档到受影响的表中,以减less对该表的访问(表扫描)。 您可能还需要validation约束一致性,启用cachingcaching,并确保索引是最佳的。

在这个过程中帮助的一个好工具是mytop ; 但mytop提供的所有信息mytop可以在mysql客户端轻松访问。 一些有用的语句来运行:

  • SHOW FULL PROCESSLIST\G获取当前正在执行的SQL语句的完整列表以及它们对服务器的状态。
  • SHOW ENGINE INNODB STATUS\G (仅限InnoDB)
  • EXPLAIN EXTENDED <QUERY>来解释你看到MySQL执行的查询。
  • SHOW GLOBAL STATUS\G显示服务器范围的状态

一旦你确定它是PHP

您可以使用工具来分析您的PHP代码(例如xdebug ),然后在KCacheGrind打开生成的configuration文件,以查看分析后的PHP代码的性能分析。

如果你发现没有这些,你可能只需要升级你的服务器。

看看我给另一个类似于这个线索的问题的答案 。

问题是,如果WordPress领域以外的其他页面加载正常,但WordPress本身被扼杀,我推荐的通用事物之外有三件事情浮现在脑海里。

  1. 当您将WordPress代码迁移到新安装程序时,是否确保在wp-config.php正确设置文件系统上的所有path? 原因是,有时WordPress可以工作,尽pipe不正确的path,如果这些设置在MySQL选项的MySQL数据库。 确保它们在wp-config.php强制WordPress使用正确的目录并确保temp和cache文件夹按预期工作。
  2. 数据库放缓? 这是唯一的事情,我可以这样做将是WordPress的特质,但允许其他网页加载。 你确定你的MySQL my.cnf正在为你的网站的数据库需求而工作吗?
  3. 你有一个插件或设置在您的WordPress代码,使Gzip压缩? 一般来说,Gzip压缩应该通过Apache或Ngnix在服务器端进行,因为他们可以比PHP代码更有效地处理Gzip压缩。 因此,如果您在WordPress中启用了cachingfunction,请禁用它,因为PHP(这是WordPress使用的)在Gzip压缩方面效果不佳。

一般来说,我已经在云服务器上安装了大量的CMS站点 – 最近的WordPress – 没有问题。 10秒的页面加载不是云主机不足的症状。 我会build议寻找我推荐的东西,在我的其他答案。 而且我还build议您在设置上进行干净的WordPress安装来进行debugging,这是一个问题,并且看看如何做出反应。 如果这与您的完整网站相比效果很好,那么您的网站特定代码显然会出现一些configuration问题。

编辑:这是另一个想法。 你有安装在任何地方的Apache授权(htaccess)吗? 你有它设置为允许从localhost ? 见下文。 有时候这个设置是有效的,但是如果Allow from localhostAllow from localhost的列表中的第一个,或者Allow的列表中唯一的项目,它可以阻止反向的DNS怪异。 我会build议尝试禁用,如果可以的话,看看网站加载速度与启用速度相比有多快。

 Order Deny,Allow Deny from all Allow from 127.0.0.1 ::1 Allow from localhost 

对于stream量较大的站点来说,最大的I / O资源之一是/tmp I / O,它来自:

  1. /tmp是为PHP会话数据读取的,对于许多CMS系统,如每个页面转换的WordPress,以确定访问者是否有权访问新页面

  2. /tmp被多次写入/读取任何SQL SELECT,其中返回的数据或创build的任何临时select集位于/ tmp

在将一台慢速机器的客户机迁移到一台新的(希望速度更快的)机器时,我所做的第一件事就是大小记忆。 我的30秒快速algorithm是:

(顶部内存使用+交换使用)* 2

然后在新机器上设置/tmp运行在tmpfs (内存)+使用mysqltuner (每隔几天)+调整mysql(真正mariadb),直到mysqltuner主要是安静的。

有时候,这个简单的技巧就是为了让一台运行缓慢的服务器重获新生。

一旦完成,那么如果机器仍然呆滞,我开始考虑调整每个子系统。

调整时,我总是从一个告诉我当前状态的工具开始。

所以对于内存大小调整,使用顶部(内存+交换+加载)。

对于Apache ,请检查日志以确保它们没有超出MaxRequestWorkers的消息。

对于旧的PHP版本,使用APC显示器来确保APC实际工作+有足够的内存空间+命中率高 – 90%以上是一个很好的目标。

对于现代PHP版本,几年前取代APC的Opcache也是如此。

对于MySQL ,首先切换到MariaDB(按照我的经验,方式更快)+每隔几天使用mysqltuner,直到输出相当安静。

对于像WordPress这样的CMS ,从来不会拿任何人的话来说明caching插件的工作原理。 使用ab来testing网站速度,首先没有任何caching+添加一个caching插件+重新testing。

提示:从ZenCache开始,你会感到惊讶。

最后,我模拟一个slowloris DDOS攻击针对我设置的每个新服务器,因为DDOS行为根据networking布局+适配器速度+机器资源的不同而不同。 我调整系统以使DDOS攻击持续足够长时间,以便Apache 4xx状态码(通常为400 + 408)显示在Apache日志中+使用fail2ban来阻止这些IP。

I / O调整的一大部分是在部署机器上的任何站点之前,生成exception的负载情况,如slowloris DDOS。 这样你就可以自己调整,而不是试图在真正的负载下调整,比如广告花费或者获得Slashdotted ……或者像DDOS或者高价值攻击那样受到攻击,或者只是一个无视robots.txt的邪恶的碎片robots.txt +吸收你的机器的所有资源。