如何排查 PHP、MySQL 和通用 I/O 的性能问题

jbx*_*jbx 4 ubuntu php performance virtual-machines wordpress

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

我计划将它移动到一个专用的虚拟服务器(Ubuntu 12.04 LTS),理论上应该会改进一些东西并使它们更加一致,因为它没有共享。但是我观察到严重的性能下降,页面需要 10 秒才能生成。

我通过/etc/hosts在服务器上进行编辑并将域映射到127.0.0.1. 我使用Apache负载测试器ab来获取HTML,所以JS,CSS和图像都被排除在外。还是花了10秒。

我在也使用 MySQL 的服务器上安装了 Zpanel,它的页面显示速度非常快(1.5 秒),还有 phpMyAdmin。直接通过 phpMyAdmin 对 wordpress 数据库执行一些查询也会很快返回它们,查询时间在 10 到 30 毫秒范围内。

内存也足够了,可用的 1Gb 物理内存中仅使用了 800Mb,因此它似乎也不是交换问题。我也安装了APC来尝试提高PHP性能,但没有任何效果。

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

我希望能够向我的提供者提出这个问题,但没有显示来自某些诊断的实际数据,我担心他只会责怪我的申请。

UPDATEsar当我没有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
Run Code Online (Sandbox Code Playgroud)

更新 2在 josten 的建议之后。

输入/输出:

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

CPU负载:

占用 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
Run Code Online (Sandbox Code Playgroud)

strace 本身使 apache 的速度减慢了 2 倍。我现在试图了解长跟踪,看看是否有任何迹象表明是什么导致了 CPU 尖峰几秒钟。

lstat性能良好的服务器的典型时间是多少?我想收集一些信息,以便我可以以建设性的方式向提供商投诉,如果是存储访问错误。

更新fio随机读取测试的输出:

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
Run Code Online (Sandbox Code Playgroud)

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

cpu          : usr=0.19%, sys=0.59%, ctx=32923, majf=0, minf=23
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

有没有我应该检查的特定设置?这些是我的设置(本地值,主值):

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
Run Code Online (Sandbox Code Playgroud)

UPDATE提高apc.shm_size到96M。缓存完整计数现在为 0,并且在多次刷新网站后,缓存的命中率为 96.5%。APC 内存使用量为 25.4MB。

它似乎将加载时间减少了 3 秒左右,如果我wget从服务器本身进行纯操作而没有获取任何图像等,现在减少到大约 4 到 5 秒。仍然比其他主机慢两倍多,但绝对是一个改进。

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

小智 11

你必须首先确定问题是什么;如果是 PHP、MySQL、I/O、负载、内存、CPU、内核等,则sar记录系统指标;你必须在行动中抓住它。您可以配置atop进行流程记帐,这绝对有帮助。

判断是否是I/O

使用iotop和等工具atop查看磁盘使用情况;这些工具还会告诉您导致 IO 的原因。通常,如果 iowait持续超过 10%,这可能是问题所在。

sar记录磁盘 IO;所以你可以跑去sar -d看它(看%util列)。

确定它是否是负载

使用诸如htop, top, 之类的工具uptime;再次将其与正在运行的进程联系起来,并找出有关进程正在执行的操作的更多详细信息。请注意,这会报告调度程序上的负载;它不反映 CPU 使用率。

判断是否是CPU

sar再次进入以挽救这一天;您可以使用 来查看此信息sar -P ALL。您还可以mpstat -P ALL用于实时数据。一般来说,只有当所有 CPU 都处于 100% 时,才会出现 CPU 问题;80%+ 意味着它们正在被使用(但不一定饱和)。

确定它是否是内存(VM)

你会想要使用vmstat; vmstat -S M 1和观察swapio以及system列。显然,大量的交换会影响性能。还有这个system部分;大量的中断也可以这样做。

判断是否中断

您可以使用vmstat -S M 1. 不幸的是,如果您的系统没有正常情况的基线,则很难判断中断是否是问题所在。大量中断(由需要内核操作的硬件引起)将使系统陷入困境。失败的 NIC 因这样做而臭名昭著。

判断是否是内核

这是棘手的,但通常需要straceperfsysdig工具。一种这样的工具是perf top. strace带有摘要 ( -c) 很好,但它不会相对于系统资源进行分解(因此提供的数据只是推测);使用它perf top来得出它是内核的结论是理想的。stap如果您的机器支持,您也可以使用(SystemTap)。我还应该指出,这strace会影响性能;sysdig如果系统很重要,您应该使用。

确定它是否是 MySQL/PHP

基本上,你必须按照我上面贴(perf例如可以提供导致高内核时间,什么命令的信息iotopatophtop可以对系统资源对什么是使用它们提供相关信息); 基本上,您正在使用上述工具来确定导致负载的原因。

一旦你确定它是 MySQL

它可能是您正在运行的查询(因此您需要EXPLAIN在 MySQL 中对该查询使用)。您还需要确保您的数据库已优化并且您正在执行的查询已优化。您还必须确保您使用的表引擎非常适合您正在做的事情(我已经看到许多大型表,但 MyISAM 应该是 InnoDB)。如果您确定以上都不是问题,并且仍然怀疑 MySQL,您可能希望在受影响的表中存档数据以减少对该表的访问(表扫描)。您可能还想验证约束一致性、启用缓存缓冲并确保索引是最佳的。

在此过程中提供帮助的一个好工具是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以查看所分析的 PHP 代码的性能分析。

如果您发现这些都不是,您可能只需要升级您的服务器。