Apache的htcacheclean不能扩展:如何驯服庞大的Apache disk_cache?

我们有一个巨大的disk_cache(> 500.000条目,> 50 GB磁盘空间使用)的Apache设置。 caching每天增长16 GB。

我的问题是,caching似乎正在增长几乎一样快,可以从caching文件系统中删除文件和目录

caching分区是iSCSI存储上的ext3文件系统(100GB,“-t news”)。 Apache服务器(充当caching代理)是一个虚拟机。 disk_cacheconfiguration了CacheDirLevels = 2和CacheDirLength = 1,并且包含变体。 典型的文件path是“/htcache/B/x/i_iGfmmHhxJRheg8NHcQ.header.vary/A/W/oGX3MAV3q0bWl30YmA_A.header”。

当我尝试调用htcacheclean来驯服caching(非守护进程模式,“htcacheclean-t -p / htcache -l15G”)时, IOwait将会经过几个小时的时间 。 没有任何可见的行动。 只有几小时后,htcacheclean才开始从caching分区中删除文件,这需要花费几个小时。 (2009年在Apache邮件列表中提出了类似的问题,但没有解决方法: http : //www.mail-archive.com/[email protected]/msg42683.html )

高IOwait会导致Web服务器的稳定性问题(通往Tomcat后端服务器的桥梁有时会停滞)。

我想出了我自己的修剪脚本,它从caching的随机子目录中删除文件和目录。 只是发现脚本删除率略高于caching增长率 。 该脚本需要大约10秒的时间来读取一个子目录(例如/ htcache / B / x),并释放一些5 MB的磁盘空间。 在这10秒内,caching又增长了2MB 。 与htcacheclean一样,在连续运行修剪脚本的时候, IOwait会上升到25%

任何想法?

  • 这是(特别慢)iSCSI存储的特定问题吗?

  • 我应该为一个巨大的disk_cacheselect一个不同的文件系统吗? EXT2? EXT4?

  • 有没有这种情况下的内核参数优化? (我已经尝试了截止日程安排程序和一个较小的read_ahead_kb,没有效果)。

dir读取10秒钟听起来像你可能不会使用dir_index

检查

/sbin/tune2fs /dev/wherever | grep dir_index 

如何打开

 tune2fs -O dir_index /dev/wherever 

但是这只会影响新创build的dirs,重新对所有运行进行重新索引

 e2fsck -D -f /dev/wherever 

通过我最近的调查,由类似的htcacheclean的辛苦所引发的,我得出结论,清洗大型或深度caching,特别是那些涉及Vary头的主要问题是实用程序本身的devise问题。

基于在源代码中查找,并观察strace -e trace = unlink的输出,一般的做法似乎如下:

  1. 遍历所有的顶级目录(/ htcache / B / x /,以上)
    • 删除已经过期的条目的任何.header和.data文件
    • 收集所有嵌套条目的元数据(上面的/htcache/B/x/i_iGfmmHhxJRheg8NHcQ.header.vary/A/W/oGX3MAV3q0bWl30YmA_A.header)
  2. 迭代所有嵌套的条目元数据,然后用响应时间清除这些元素,将来的.header modtime或.data modtime
  3. 迭代所有嵌套的条目元数据,并清除已过期的元素
  4. 迭代所有嵌套的条目元数据以查找最老的; 清除它; 重复

并且一旦高速caching大小下降到低于设定的阈值,最后三个步骤中的任何一个将从清除子程序返回。

所以随着快速增长和/或已经大的高速caching,步骤#1所需的延长时间内的增长速率即使一旦进入步骤#2-#4也可以容易地certificate是不可克服的。

进一步复杂的问题,如果你还没有满足第二步结束时的大小限制,你必须迭代嵌套条目的所有元数据才能find最老的,以便只删除那个单一的入口,然后再一次做同样的事情,这意味着caching再次被允许增长速度比你将永远能够修剪它。

 /* process remaining entries oldest to newest, the check for an emtpy * ring actually isn't necessary except when the compiler does * corrupt 64bit arithmetics which happend to me once, so better safe * than sorry */ while (sum > max && !interrupted && !APR_RING_EMPTY(&root, _entry, link)) { oldest = APR_RING_FIRST(&root); for (e = APR_RING_NEXT(oldest, link); e != APR_RING_SENTINEL(&root, _entry, link); e = APR_RING_NEXT(e, link)) { if (e->dtime < oldest->dtime) { oldest = e; } } delete_entry(path, oldest->basename, pool); sum -= oldest->hsize; sum -= oldest->dsize; entries--; APR_RING_REMOVE(oldest, link); } 

解决scheme?

明显快(呃)磁盘将有所帮助。 但对于我来说,IO吞吐量的增长需要多less时间才能克服目前htcacheclean方法中的固有问题,这一点我不清楚。 没有对创造者或维护者的挖掘,但它似乎确实似乎这个devise要么没有testing,要么没有预料到对广泛,深入,快速增长的cachingperformance良好。

但似乎工作,而且我现在还在确认,是从本身循环顶层目录的bash脚本中触发htcacheclean。

 #!/bin/bash # desired cache size in integer gigabytes SIZE=12; # divide that by the number of top-level directories (4096), # to get the per-directory limit, in megabytes LIMIT=$(( $SIZE * 1024 * 1024 * 1024 / 4096 / 1024 / 1024 ))M; while true; do for i in /htcache/*/*; do htcacheclean -t -p$i -l$LIMIT; done; done; 

基本上,这种方法可以让你更快,更频繁地进入清除步骤(#2-#4),即使只有一小部分条目。 这意味着您有可能以比添加到caching的速度快的速度清除内容。 再次,它似乎为我们工作,但我只testing了几天。 而我们的caching目标和增长速度似乎与您的一致,但最终您的里程可能会有所不同。

当然这个post的主要观点是,也许这样做会有助于其他人以同样的方式绊倒这个问题。