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。为什么它如此占用资源?一个ls
会话目录/var/lib/php5
只需要几分之一秒。那么为什么修剪旧会话需要整整 25 分钟?我能做些什么来加快速度吗?
该设备的文件系统目前是 ext4,在 Ubuntu Precise 12.04 64 位上运行。
编辑:我怀疑负载是由于不寻常的过程“fuser”造成的(因为我希望一个简单rm
的东西比我看到的性能更快)。我将删除 fuser 的使用,看看会发生什么。
祝贺您拥有一个受欢迎的网站,并设法让它一直在虚拟机上运行。
如果你真的每天有 200 万的页面浏览量,那么你将在文件系统中堆积大量的 PHP 会话,无论你使用
fuser
orrm
还是删除它们都需要很长时间吸尘器。在这一点上,我建议您研究存储会话的替代方法:
memcached
. 这快如闪电,但如果服务器崩溃或重新启动,您的所有会话都会丢失并且每个人都会注销。删除
fuser
应该有帮助。此作业fuser
为找到的每个会话文件运行一个命令(检查文件当前是否打开),这在具有 14k 会话的繁忙系统上很容易花费几分钟。这是一个 Debian 错误(Ubuntu 基于 Debian)。除了 memcached,您还可以尝试使用 tmpfs(内存中的文件系统)来存储会话文件。与 memcached 一样,这会在重启时使会话无效(这可以通过在关闭脚本中的某处备份此目录并在启动脚本中恢复来解决),但设置起来会容易得多。但这无助于
fuser
解决问题。因此,此处用户建议的 Memcached 和数据库会话存储选项都是提高性能的不错选择,各有优缺点。
但是通过性能测试,我发现这个session维护的巨大性能开销几乎全部归结
fuser
于cron作业中的调用。这是恢复到 Natty / Oneiric cron 作业后的性能图,该作业使用rm
而不是fuser
修剪旧会话,切换发生在 2:30。您可以看到由 Ubuntu 的 PHP 会话清理导致的周期性性能下降几乎完全消除了。磁盘操作图中显示的尖峰现在幅度小得多,并且与该图可能测量的一样细,显示了一个小的、短暂的中断,之前服务器性能显着下降了 25 分钟。完全消除了额外的 CPU 使用,现在这是一个 IO 绑定的工作。
(一个不相关的 IO 作业在 05:00 运行,而 CPU 作业在 7:40 运行,这两者都会在这些图表上造成它们自己的峰值)
我现在正在运行的修改后的 cron 作业是:
我在对会话进行一些研究时遇到了这篇文章。虽然公认的答案非常好(并且 fuser 调用已从 gc 脚本中删除了一段时间),但我认为如果其他人遇到类似问题,还需要注意其他一些注意事项。
在所描述的场景中,OP 使用的是 ext4。ext4 中的目录以 htree 数据库格式存储文件数据——这意味着与将大量文件分布在多个目录中相比,将大量文件保存在单个目录中的影响可以忽略不计。并非所有文件系统都是如此。PHP 中的默认处理程序允许您为会话文件使用多个子目录(但请注意,您应该检查控制进程是否递归到这些目录中 - 上面的 cron 作业不会)。
很多操作成本(在删除对 fuser 的调用之后)来自于查看尚未过时的文件。使用(例如)单一级别的子目录,以及在每个子目录(0/、1/、...d/、e/、f/)中查找的 16 个 cron 作业将消除出现的负载颠簸。
使用具有更快衬底的自定义会话处理程序会有所帮助 - 但有很多选择(memcache,redis,mysql 处理程序套接字......)撇开互联网上发布的质量范围不谈,你选择取决于确切关于您的应用程序、基础设施和技能的要求,不要忘记与默认处理程序相比,在处理语义(特别是锁定)方面经常存在差异。
对于这种流量,您不应该将会话放在磁盘上。你应该使用像 memcache 这样的东西。您所要做的就是设置 php,无需更改代码。参见示例
http://www.dotdeb.org/2008/08/25/storing-your-php-sessions-using-memcached/
之所以花费这么长时间,是因为它必须对大量文件进行分类以查看哪些文件可以删除。根据您在代码中设置的会话长度,内存缓存可以自动使这些过期。