问题描述
Ubuntu设置了一个cron作业,用于查找和删除旧的PHP会话:
# Look for and purge old sessions every 30 minutes
09,39 * * * * root [ -x /usr/lib/php5/maxlifetime ] \
&& [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 \
-maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) ! -execdir \
fuser -s {} 2> /dev/null \; -delete
我的问题是,此过程需要很长时间才能运行,并且有很多磁盘IO。这是我的CPU使用率图表:
蓝绿色尖峰代表清理运行。在此期间的开始,PHP的清理作业计划为默认的09和39分钟时间。在15:00时,我从cron中删除了39分钟的时间,因此清理工作的速度是大小的两倍(您可以看到峰的宽度是原来的两倍,峰的频率是原来的两倍)。
以下是IO时间的相应图表:
和磁盘操作:
在大约14,000个会话处于活动状态的高峰期,可以看到清理运行了整整25分钟,显然是整个周期使用了100%的一个CPU内核,似乎使用了100%的磁盘IO。为什么如此耗费资源?会话目录/var/lib/php5
的ls
仅花费一秒钟的时间。那么,为什么要花整整25分钟来整理旧的会话?我有什么办法可以加快速度?
该设备的文件系统当前为ext4,在64位Ubuntu Precise 12.04上运行。
编辑:我怀疑负载是由于异常的过程”fuser”(因为我期望一个简单的rm
比我看到的性能要快得多)。我将删除热熔器的使用,然后看看会发生什么。
最佳方法
删除fuser
应该会有所帮助。该作业为找到的每个会话文件运行fuser
命令(检查当前是否打开了文件),在繁忙的系统上有14k个会话时,这很容易花费几分钟。这个was a Debian bug(Ubuntu基于Debian)。
除了memcached,您还可以尝试将tmpfs(内存中的文件系统)用于会话文件。像memcached一样,这会使重新启动时的会话无效(可以通过在关闭脚本中备份该目录并在启动脚本中进行还原来解决此问题),但安装起来会容易得多。但这对解决fuser
问题没有帮助。
次佳方法
祝贺您拥有一个受欢迎的网站,并一直保持其在虚拟机上的运行。
如果您确实每天要吸引200万次页面访问,那么您将在文件系统中堆积很多PHP会话,无论您使用fuser
还是rm
,它们都将需要很长时间才能删除或吸尘器。
在这一点上,我建议您考虑使用其他方法来存储会话:
-
一种选择是将会话存储在
memcached
中。闪电般快速,但是如果服务器崩溃或重新启动,则所有会话都将丢失,所有人都将注销。 -
您还可以将会话存储在数据库中。这将比memcached慢一些,但是数据库将是持久性的,您可以使用简单的SQL查询清除旧会话。但是,要实现此目的,您必须使用write a custom session handler。
第三种方法
因此,此处用户建议的Memcached和数据库会话存储选项都是提高性能的不错选择,每一个都有各自的优点和缺点。
但是通过性能测试,我发现此会话维护的巨大性能成本几乎完全归功于cron作业中对fuser
的调用。这是恢复到Natty /Oneiric cron作业后的性能图,该作业使用rm
而不是fuser
来修剪旧会话,切换发生在2:30。
您可以看到,几乎完全消除了因Ubuntu的PHP会话清理而导致的定期性能下降。现在,“磁盘操作”图中的尖峰的数量级要小得多,并且可以像此图所测量的那样纤细,这显示了一个短暂的小中断,以前的服务器性能在25分钟内已显著降低。完全消除了额外的CPU使用率,这现在是IO-bound作业。
(不相关的IO作业在05:00运行,CPU作业在7:40运行,这两个原因都会在这些图表上导致它们各自的峰值)
我现在正在运行的修改后的cron作业是:
09 * * * * root [ -x /usr/lib/php5/maxlifetime ] && \
[ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 \
-maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 \
| xargs -n 200 -r -0 rm