cyb*_*x86 9 ext4 io amazon-ebs alternative-php-cache
问题: 我最近改造了我的一台服务器,它在使用前进行了测试,并且运行良好,但是,几天前,我注意到对根卷的写入量大约是通常的 4 倍。这不是性能问题 - 服务器运行良好。
我的改造相当广泛(完全重建),所以就原因而言,我没有太多事情要做。简而言之,我的变化包括:
基本设置:
free和iostat显示最小的交换使用)。mount --bind)。底层 EBS 卷安装在/mnt/data新设置比旧系统运行“更流畅”(更快、更少内存等),并且已经稳定了 20 天(10 月中旬)——据我所知,提升的写入一直存在.
与我的预期相反,我的读取量很低(我的读取量约占写入量的 1.5%,无论是在我的根卷上的块还是字节数)。在过去的几天里,我没有对根卷(例如新安装等)进行任何更改,但写入量仍然比预期高得多。
目标:确定对根卷的写入增加的原因(本质上,确定它是一个进程(以及哪个进程)、不同的(ext4)文件系统或其他问题(例如内存))。
系统信息:
根卷和数据卷每天创建一次快照——但是,这应该是“读”操作,而不是写操作。(另外,同样的做法也用在了之前的服务器上——而且之前的服务器也是一个 t1.micro。)
导致我查看 I/O 的数据在我上次 AWS 账单的详细信息中(I/O 高于正常水平 - 这并不意外,因为我正在设置此服务器,并在开始时安装了很多东西月),然后是附加的 EBS 卷的 CloudWatch 指标。我通过推断 11 月的 I/O 活动(当我没有更改服务器时)来估计每月的值并将其与过去几个月我不工作时的 I/O 进行比较,从而得出“正常的 4 倍”数字在我以前的服务器上。(我没有来自我以前的服务器的确切 iostat 数据)。相同数量的写入一直持续到 11 月,170-330MB/小时。
诊断信息(以下输出的正常运行时间为 20.6 天):
Cloudwatch 指标:
输出:(df -h仅适用于根卷)
Filesystem Size Used Avail Use% Mounted on
/dev/xvda1 4.0G 1.2G 2.8G 31% /
Run Code Online (Sandbox Code Playgroud)
自该系统启动以来,已用空间没有明显增加(对我而言,这表明正在更新文件,而不是创建/附加文件)。
输出:(iostat -x带Blk_read,Blk_wrtn添加):
Linux 2.6.35.14-95.38.amzn1.i686 11/05/2011 _i686_
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s Blk_read Blk_wrtn avgrq-sz avgqu-sz await svctm %util
xvdap1 0.00 3.42 0.03 2.85 0.72 50.19 2534636 177222312 17.68 0.18 60.93 0.77 0.22
xvdf 0.00 0.03 0.04 0.35 1.09 8.48 3853710 29942167 24.55 0.01 24.28 2.95 0.12
xvdg 0.00 0.00 0.00 0.00 0.02 0.04 70808 138160 31.09 0.00 48.98 4.45 0.00
Run Code Online (Sandbox Code Playgroud)
输出: iotop -d 600 -a -o -b
Total DISK READ: 6.55 K/s | Total DISK WRITE: 117.07 K/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND
852 be/4 root 0.00 B 26.04 M 0.00 % 0.42 % [flush-202:1]
539 be/3 root 0.00 B 528.00 K 0.00 % 0.08 % [jbd2/xvda1-8]
24881 be/4 nginx 56.00 K 120.00 K 0.00 % 0.01 % nginx: worker process
19754 be/4 mysql 180.00 K 24.00 K 0.00 % 0.01 % mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
3106 be/4 mysql 0.00 B 176.00 K 0.00 % 0.00 % mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
19751 be/4 mysql 4.00 K 0.00 B 0.00 % 0.00 % mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
3194 be/4 mysql 8.00 K 40.00 K 0.00 % 0.00 % mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
3156 be/4 mysql 4.00 K 12.00 K 0.00 % 0.00 % mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
3099 be/4 mysql 0.00 B 4.00 K 0.00 % 0.00 % mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
24216 be/4 web14 8.00 K 10.43 M 0.00 % 0.00 % php-fpm: pool web14
24465 be/4 web19 0.00 B 7.08 M 0.00 % 0.00 % php-fpm: pool web19
3110 be/4 mysql 0.00 B 100.00 K 0.00 % 0.00 % mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
579 be/4 varnish 0.00 B 76.00 K 0.00 % 0.00 % varnishd -P /var/run/varnish.pid -a :80 -f /etc/varnish/default.vcl -T 127.0.0.1:6082 -t 3600 -w 1,1000,120 -u varnish -g varnish
582 be/4 varnish 0.00 B 144.00 K 0.00 % 0.00 % varnishd -P /var/run/varnish.pid -a :80 -f /etc/varnish/default.vcl -T 127.0.0.1:6082 -t 3600 -w 1,1000,120 -u varnish -g varnish
586 be/4 varnish 0.00 B 4.00 K 0.00 % 0.00 % varnishd -P /var/run/varnish.pid -a :80 -f /etc/varnish/default.vcl -T 127.0.0.1:6082 -t 3600 -w 1,1000,120 -u varnish -g varnish
587 be/4 varnish 0.00 B 40.00 K 0.00 % 0.00 % varnishd -P /var/run/varnish.pid -a :80 -f /etc/varnish/default.vcl -T 127.0.0.1:6082 -t 3600 -w 1,1000,120 -u varnish -g varnish
1648 be/4 nobody 0.00 B 8.00 K 0.00 % 0.00 % in.imapproxyd
18072 be/4 varnish 128.00 K 128.00 K 0.00 % 0.00 % varnishd -P /var/run/varnish.pid -a :80 -f /etc/varnish/default.vcl -T 127.0.0.1:6082 -t 3600 -w 1,1000,120 -u varnish -g varnish
3101 be/4 mysql 0.00 B 176.00 K 0.00 % 0.00 % mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
19749 be/4 mysql 0.00 B 32.00 K 0.00 % 0.00 % mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
19750 be/4 mysql 0.00 B 0.00 B 0.00 % 0.00 % mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
19752 be/4 mysql 0.00 B 108.00 K 0.00 % 0.00 % mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
19788 be/4 mysql 0.00 B 12.00 K 0.00 % 0.00 % mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
853 be/4 root 4.00 K 0.00 B 0.00 % 0.00 % [flush-202:80]
22011 be/4 varnish 0.00 B 188.00 K 0.00 % 0.00 % varnishd -P /var/run/varnish.pid -a :80 -f /etc/varnish/default.vcl -T 127.0.0.1:6082 -t 3600 -w 1,1000,120 -u varnish -g varnish
Run Code Online (Sandbox Code Playgroud)
总结以上(并推断到每日值),在 10 分钟内看起来像:
有趣的是,它会出现之间[flush-202],并php-fpm有可能占了成交量的写入。
使用ftop,我无法追踪flush或php-fpm写入(例如ftop -p php-fpm.
我的问题至少部分源于识别哪些进程正在写入根卷。的上面列出的那些,我希望所有被写入的数据量(由于相关目录符号链接有)(例如nginx,mysql,php-fpm,varnish目录都指向一个不同的EBS卷)
我相信JBD2是 ext4 的日志块设备,flush-202是脏页的后台刷新。的dirty_ratio是20和dirty_background_ratio10。脏存储器(从/proc/meminfo)是典型地50-150kB之间)。页面大小 ( getconf PAGESIZE) 是系统默认值 (4096)。
输出: vmstat -s | grep paged
3248858 页调入 104625313 页调出
输出: sar -B | grep Average
pgpgin/s pgpgout/s fault/s majflt/s pgfree/s pgscank/s pgscand/s pgsteal/s %vmeff
Average: 1.38 39.57 113.79 0.03 36.03 0.38 0.02 0.29 73.66
Run Code Online (Sandbox Code Playgroud)
以上似乎表明有大量页面被调出 - 但是,我希望在必要时将页面写入我的交换分区,而不是我的根卷。在总内存中,系统通常有 35% 正在使用,10% 在缓冲区中,40% 已缓存,15% 未使用(即 65% 空闲)。
输出: vmstat -d
disk- ------------reads------------ ------------writes----------- -----IO------
total merged sectors ms total merged sectors ms cur sec
xvda1 105376 14592 2548092 824418 10193989 12264020 179666824 626582671 0 7872
xvdf 126457 579 3882950 871785 1260822 91395 30081792 32634413 0 4101
xvdg 4827 4048 71000 21358 1897 15373 138160 307865 0 29
Run Code Online (Sandbox Code Playgroud)
vmstat始终显示si且so值为 0
输出: swapon -s
Filename Type Size Used Priority
/dev/xvdg partition 1048572 9252 -1
Run Code Online (Sandbox Code Playgroud)
预感 I/O 写入可能与内存有关,我禁用了清漆,并重新启动了服务器。这将我的内存配置文件更改为 10% 使用,2% 缓冲区,20% 缓存,68% 未使用(即 90% 空闲)。然而,在 10 分钟的运行中,iotop 给出了与之前类似的结果:
在重新启动后的一个小时内,已经有 330MB 的空间写入根卷,交换了 370K 个页面。
输出 inotifywatch -v -e modify -t 600 -r /[^mnt]*
Establishing watches...
Setting up watch(es) on /bin /boot /cgroup /dev /etc/ home /lib /local /lost+found /opt /proc /root /sbin /selinux /src /sys /usr /var
OK, /bin /boot /cgroup /dev /etc/ home /lib /local /lost+found /opt /proc /root /sbin /selinux /src /sys /usr /var is now being watched.
Total of 6753 watches.
Finished establishing watches, now collecting statistics.
Will listen for events for 600 seconds.
total modify filename
23 23 /var/log/
20 20 /usr/local/ispconfig/server/temp/
18 18 /dev/
15 15 /var/log/sa/
11 11 /var/spool/postfix/public/
5 5 /var/log/nginx/
2 2 /var/run/pure-ftpd/
1 1 /dev/pts/
Run Code Online (Sandbox Code Playgroud)
进一步研究上述内容,几乎所有写入都可以归因于每 5 分钟运行一次并检查各种服务状态的(未知)进程(例如chkservd在 cPanel 上,但我不使用 cPanel,并且没有安装这个)。在 10 分钟内更新了 4 个日志文件(cron、maillog、ftp、imapproxy) - 以及一些相关项目(后缀套接字、纯 ftpd 连接)。其他项目主要是修改的 ispconfig 会话、系统记帐更新和无效(不存在的 server_name)Web 访问尝试(记录到 /var/log/nginx)。
结论和问题:
首先让我说我有点困惑 - 我通常相当彻底,但我觉得我在这个问题上遗漏了一些明显的东西。显然,flush并且php-fpm占写入的大部分,但是,我不知道为什么会出现这种情况。首先,让我们使用 php-fpm - 它甚至不应该写入根卷。它的目录(文件和日志)被符号链接到另一个 EBS 卷。其次,php-fpm 应该编写的主要内容是会话和页面缓存——它们既少又小——当然不是 1MB/min 的数量级(更像是 1K/min,如果那样的话)。大多数站点都是只读的,只有偶尔更新。最后一天修改的所有网页文件总大小为 2.6MB。
其次,考虑刷新——它的重要写入向我表明脏页经常被刷新到磁盘——但考虑到我通常有 65% 的可用内存和一个单独的 EBS 卷用于交换空间,我无法解释为什么会这样影响我的根卷上的写入,尤其是在发生的范围内。我意识到有些进程会将脏页写入它们自己的交换空间(而不是使用系统交换空间),但是可以肯定的是,在我的绝大多数内存空闲的情况下重新启动后,我不应该遇到任何大量的脏页。如果您确实认为这是原因,请告诉我如何识别哪些进程正在写入它们自己的交换空间。
整个脏页的想法完全有可能只是一个红鲱鱼,与我的问题完全无关(我希望它实际上是)。如果是这种情况,我唯一的另一个想法是,ext3 中不存在与 ext4 日志相关的某些内容。除此之外,我目前没有想法。
更新):
2011 年 11 月 6 日:
设置dirty_ratio = 10和dirty_background_ratio = 5; 更新sysctl -p(通过 /proc 确认);重新运行 10 分钟 iotop 测试,结果相似(flush 写入 17MB,php-fpm 写入 16MB,MySQL 写入 1MB,JBD2 写入 0.7MB)。
我已经更改了我设置的所有符号链接mount --bind。重新启用清漆,重新启动服务器;重新运行 10 分钟 iotop 测试,结果相似(flush 写入 12.5MB,php-fpm 写入 11.5MB,Varnish 写入 0.5MB,JBD2 写入 0.5MB,MySQL 写入 0.3MB)。
在上面的运行中,我的内存配置文件是 20% 正在使用,2% 在缓冲区中,58% 被缓存,20% 未使用(即 80% 空闲)以防万一我对空闲内存的解释,在这种情况下,是有缺陷的,这是free -m(这是一个 t1.micro)的输出。缓存的已用空闲共享缓冲区总数:602 478 124 0 14 347 -/+ 缓冲区/缓存:116 486 交换:1023 0 1023
一些附加信息: 输出: dmesg | grep EXT4
[ 0.517070] EXT4-fs (xvda1): mounted filesystem with ordered data mode. Opts: (null)
[ 0.531043] EXT4-fs (xvda1): mounted filesystem with ordered data mode. Opts: (null)
[ 2.469810] EXT4-fs (xvda1): re-mounted. Opts: (null)
Run Code Online (Sandbox Code Playgroud)
我还同时运行了 ftop 和 iotop,并惊讶地发现 iotop 中显示的条目没有出现在 ftop 中。ftop 列表被过滤到 php-fpm,因为我可以相当可靠地触发该进程的写入。我注意到 php-fpm 的每个页面视图写入了大约 2MB - 我还没有弄清楚它可能在写什么 - 任何关于确定正在写什么的想法都将不胜感激。
在接下来的几天里,我将尝试关闭日记功能,看看是否能改善情况。不过,就目前而言,我发现自己想知道我是否有 I/O 问题或内存问题(或两者都有)——但我很难看到内存问题,如果有的话。
2011 年 11 月 13 日:
由于文件系统使用范围,因此无法将其挂载为 ext3,此外,尝试将其挂载为只读,只会导致将其重新挂载为读写。
文件系统确实启用了日志功能(128MB 日志),如下所示:
输出: tune2fs -l /dev/sda1 | grep features
has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Run Code Online (Sandbox Code Playgroud)
根据以下内容,在不到一个月的时间里,大约 140GB 已写入此卷 - 仅约 5GB/天。
输出: dumpe2fs -h /dev/sda1
Filesystem volume name: /
Last mounted on: /
Filesystem UUID: af5a3469-6c36-4491-87b1-xxxxxxxxxxxx
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags: signed_directory_hash
Default mount options: (none)
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 262144
Block count: 1048576
Reserved block count: 10478
Free blocks: 734563
Free inodes: 210677
First block: 0
Block size: 4096
Fragment size: 4096
Reserved GDT blocks: 511
Blocks per group: 32768
Fragments per group: 32768
Inodes per group: 8192
Inode blocks per group: 512
RAID stride: 32582
Flex block group size: 16
Filesystem created: Wed Sep 21 21:28:43 2011
Last mount time: Sun Nov 13 16:10:11 2011
Last write time: Sun Oct 16 16:12:35 2011
Mount count: 13
Maximum mount count: 28
Last checked: Mon Oct 10 03:04:13 2011
Check interval: 0 (<none>)
Lifetime writes: 139 GB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256
Required extra isize: 28
Desired extra isize: 28
Journal inode: 8
First orphan inode: 18610
Default directory hash: half_md4
Directory Hash Seed: 6c36b2cc-b230-45e2-847e-xxxxxxxxxxx
Journal backup: inode blocks
Journal features: journal_incompat_revoke
Journal size: 128M
Journal length: 32768
Journal sequence: 0x0002d91c
Journal start: 1
Run Code Online (Sandbox Code Playgroud)
继续寻找打开的文件,我尝试fuser在根卷上使用:
输出: fuser -vm / 2>&1 | awk '$3 ~ /f|F/'
root 1111 Frce. dhclient
root 1322 frce. mysqld_safe
mysql 1486 Fr.e. mysqld
root 1508 Frce. dovecot
root 1589 Frce. master
postfix 1600 Frce. qmgr
root 1616 Frce. crond
root 1626 Frce. atd
nobody 1648 Frce. in.imapproxyd
postfix 1935 Frce. tlsmgr
root 2808 Frce. varnishncsa
root 25818 frce. sudo
root 26346 Fr.e. varnishd
postfix 26925 Frce. pickup
postfix 28057 Frce. smtpd
postfix 28070 Frce. showq
Run Code Online (Sandbox Code Playgroud)
不幸的是,没有什么意外。由于底层硬件的原因,我恢复了昨天的根卷快照(最后一天没有任何变化),并用新的根卷替换了实例的根卷。正如预期的那样,这对问题没有影响。
我的下一步是删除日志,但是在开始之前我偶然发现了解决方案。
问题在于使用文件支持的 mmap 的 APC。将这个下降的磁盘 i/o 修复了大约 35 倍 - 到(估计)150MB/天(而不是 5GB)。我可能仍然会考虑删除日志,因为这似乎是该值的主要剩余贡献者,但是,这个数字暂时是可以接受的。得出 APC 结论所采取的步骤已发布在下面的答案中。
由于主要原因似乎是写日记,这将是我的下一步。但是,为了删除日志,我需要将 EBS 卷附加到另一个实例。我决定使用(一天前的)快照来测试该过程,但是,在删除日志之前,我重新运行了 10 分钟的 iotop 测试(在测试实例上)。令我惊讶的是,我看到了正常(即未升高)的值,这是第一次flush-202甚至没有出现在列表中。这是一个功能齐全的实例(我也恢复了我的数据的快照)- 根卷自拍摄以来的 12 小时左右没有发生任何变化。所有测试都表明,两台服务器上都在运行相同的进程。这让我相信原因必须归结为“实时”服务器正在处理的一些请求。
查看显示问题的服务器的 iotop 输出与看似没有问题的服务器的 iotop 输出之间的差异,唯一的区别是flush-202和php-fpm。这让我想到,虽然很远,但可能是与 PHP 配置相关的问题。
现在,这部分并不理想 - 但由于在实时服务器上运行的任何服务都不会受到几分钟的停机时间的影响,所以这并不重要。为了缩小问题的范围,实时服务器上的所有主要服务(postfix、dovecot、imapproxy、nginx、php-fpm、varnish、mysqld、varnishncsa)都已停止,并重新运行 iotop 测试 - 没有提升磁盘 i/o . 服务分3批重启,把php-fpm留到最后。每批重启后iotop测试确认没有问题。一旦 php-fpm 启动,问题就会返回。(在测试服务器上模拟一些 PHP 请求本来很容易,但此时,我不确定它是否真的是 PHP)。
不幸的是,如果没有 PHP,服务器将毫无意义,所以这不是一个理想的结论。然而,由于flush-202似乎暗示了一些与内存有关的东西(尽管有足够的可用内存),我决定禁用 APC。重新运行 iotop 测试显示磁盘 i/o 级别正常。对此事的仔细研究表明已启用 mmap,并将其 apc.mmap_file_mask设置为/tmp/apc.XXXXXX(此安装的默认设置)。该路径将 APC 设置为使用文件支持的 mmap。简单地注释掉这一行(因此使用默认值 - 匿名内存支持)并重新运行 iotop 测试表明问题已解决。
我仍然不知道为什么没有一个诊断运行没有将写入识别为来自 php 并转到 /tmp 目录中的 apc 文件。唯一提到 /tmp 目录的测试是lsof,但是,它列出的文件不存在。
| 归档时间: |
|
| 查看次数: |
1391 次 |
| 最近记录: |