NFS 共享上的 Drupal 性能很差

NFS 共享上的 Drupal 性能很差

我们有一个 Drupal 7 站点,其设置如下 - 运行 web vm 和 NFS VM 的 VMware ESXi 4.1 主机服务器。web VM 使用 Apache 和 mod_php。该站点仍在开发中,因此由于文件更新频繁,我们必须关闭所有形式的缓存。

每个页面请求大约需要 15-20 秒才能完成。分析 PHP 代码显示,绝大部分时间(通常超过 90%)都花在了加载模块的所有 is_dir()、is_file() 函数调用上。

我将 PHP 的 realpath 缓存大小增加到几兆,strace 显示 lstat 调用从 200 多个减少到 6 个左右,stat() 也减少了一点(大约 600 个调用)。然而,虽然这节省了不少时间,但我还是无法突破最苛刻的页面每次请求 10 秒的限制。

有没有一种方法可以从不涉及缓存的设置中获得更好的性能?

编辑:MySQL 不是问题,查询缓存意味着请求最多需要一秒钟才能完成。

配置和统计:

VM 主机:单个四核 Xeon CPU

虚拟机:

web - Centos 6 64bt,2.5GB RAM,正常 CPU/HD 优先级(2 核) nfs - Centos 6 64bt,2GB RAM,正常 CPU 优先级(4 核),高 HD 优先级

PHP:32M 真实路径缓存大小(出于测试目的,这个值太高了)

NFS:

~]# egrep -v '#|^$' /etc/nfsmount.conf 
[ NFSMount_Global_Options ]
 Defaultvers=4
 Ac=False
 Rsize=32k
 Wsize=32k
 Bsize=32k

通过 NFS 读取速度不是问题,使用 32k 块对 100M 测试文件进行 dd 返回:

3200+0 records in
3200+0 records out
104857600 bytes (105 MB) copied, 1.84984 s, 56.7 MB/s

real    0m1.857s
user    0m0.007s
sys 0m0.330s 

在具有空真实路径缓存的 Apache 进程上进行 Strace:

    % time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 50.78    1.157452         337      3434        28 stat
 32.58    0.742656         628      1182       425 open
  9.29    0.211788         762       278         1 lstat
  3.17    0.072322           0    237865           write
  2.45    0.055839         490       114        13 access
  0.45    0.010262          43       237           brk
  0.34    0.007725          10       811        74 read
  0.28    0.006340           9       679           fstat
  0.22    0.005069          18       281           poll
  0.20    0.004533           6       698           getdents
  0.09    0.001960          10       190           mmap
  0.05    0.001065          14        74           accept4
  0.04    0.001000         333         3           chdir
  0.03    0.000750           4       190           munmap
  0.01    0.000339           0       836           close
  0.01    0.000247           3        75           writev
  0.00    0.000068           0       611           fcntl
  0.00    0.000063           1        77           shutdown
  0.00    0.000000           0         1           lseek
  0.00    0.000000           0         5           rt_sigaction
  0.00    0.000000           0         1           rt_sigprocmask
  0.00    0.000000           0         3           setitimer
  0.00    0.000000           0         5           socket
  0.00    0.000000           0         5         5 connect
  0.00    0.000000           0        74           getsockname
  0.00    0.000000           0        15           setsockopt
  0.00    0.000000           0         5           getcwd
  0.00    0.000000           0         1           futex
------ ----------- ----------- --------- --------- ----------------

缓存真实路径后进行 Strace

    % time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 60.14    1.371006         484      2831        28 stat
 31.79    0.724705         627      1155       425 open
  3.53    0.080354           0    237865           write
  2.65    0.060433         530       114        13 access
  0.43    0.009913          99       100           brk
  0.38    0.008730          11       804        74 read
  0.35    0.007910          12       675           fstat
  0.30    0.006775          10       654           getdents
  0.13    0.003065          11       281           poll
  0.09    0.002000         333         6         1 lstat
  0.07    0.001545           2       807           close
  0.05    0.001063          14        74           accept4
  0.04    0.001000           6       179           mmap
  0.02    0.000404           2       179           munmap
  0.01    0.000271           4        75           writev
  0.01    0.000212           0       611           fcntl
  0.01    0.000129           2        77           shutdown
  0.00    0.000022           0        74           getsockname
  0.00    0.000000           0         1           lseek
  0.00    0.000000           0         5           rt_sigaction
  0.00    0.000000           0         1           rt_sigprocmask
  0.00    0.000000           0         3           setitimer
  0.00    0.000000           0         3           socket
  0.00    0.000000           0         3         3 connect
  0.00    0.000000           0        15           setsockopt
  0.00    0.000000           0         5           getcwd
  0.00    0.000000           0         3           chdir
------ ----------- ----------- --------- --------- ----------------

山:

nfs.xxx.xxx.xxx:/path/to/website/files on /path/to/website/files type nfs (rw,hard,intr,noac,vers=4,addr=xx.xx.xx.xx,clientaddr=xx.xx.xx.xx)

我们当然感谢任何帮助。

答案1

坦率地说,NFS 上的 Drupal 真是个庞然大物。您最多只想通过 NFS 或类似 gluster 的东西来共享“文件”目录。在 NFS 上运行 DocRoot 的问题是,加起来,所有的 lstat(2) 和 access(2) 调用都是杀手级的,更不用说您将在模块目录中看到的 getdents(2) 和朋友了。类似 APC 的东西将大大有助于实际的 read(2) 时间,并消除编译延迟,但 PHP 仍将对每个文件执行 lstat(2) 和 access(2)。为了进一步加快速度,您可以设置 apc.stat=0,但如果您经常更改 PHP 文件,那么这将无济于事,正如您所说的那样,除非您愿意在每次进行此类更改时重新启动 Apache(或通过 apc.php 手动清除 APC 缓存)。

最佳实践建议将 DocRoot 存储在专用的优化设备(例如 SAN)上,或单独存储在每个 Webhead 上。“文件”目录通常应通过 gluster/nfs/etc 共享,但作为替代方案,您也可以定期在服务器之间 rsync 它,具体取决于用例以及前端的 LB 是否支持粘性会话。您还可以通过使用 CDN 或 Amazon 的 S3 或 BlackMesh 的 Swift 等服务完全消除文件目录。

拥有 Drupal 详细专业知识的托管服务提供商可以帮助您解决其中一些架构问题;您可能希望联系 Acquia 或 BlackMesh(我为后者工作)。我不知道 Acquia 是否提供,但我知道 BlackMesh 还提供场外协助,我们与您现有的托管服务提供商或现场托管合作,以优化 Drupal 解决方案。

祝您的网站好运!

答案2

一般情况下,使用 mount 进行挂载noac都会影响性能。

你为什么要用它?

编辑:我看到上面的评论中说您稍后会添加更多 Web 服务器和负载平衡器。正如 BMDan 所建议的,如果您的应用程序需要使用,您应该研究集群文件系统(例如 OCFS2)noac

干杯

相关内容