O htcacheclean do Apache não é escalável: como domar um enorme disk_cache do Apache?

6

Temos uma configuração do Apache com um enorme disk_cache (> 500.000 entradas, > 50 GB de espaço em disco usado). O cache cresce 16 GB por dia.

Meu problema é que o cache parece estar crescendo quase tão rápido quanto é possível remover arquivos e diretórios do sistema de arquivos em cache !

A partição de cache é um sistema de arquivos ext3 (100GB, "-t news") em um armazenamento iSCSI. O servidor Apache (que age como um proxy de armazenamento em cache) é uma VM. O disk_cache é configurado com CacheDirLevels = 2 e CacheDirLength = 1 e inclui variantes. Um caminho de arquivo típico é "/htcache/B/x/i_iGfmmHhxJRheg8NHcQ.header.vary/A/W/oGX3MAV3q0bWl30YmA_A.header".

Quando tento chamar htcacheclean para domar o cache (modo não daemon, "htcacheclean-t -p / htcache-l15G"), o IOwait está passando pelo telhado por vários horas . Sem qualquer ação visível. Somente depois de horas, o htcacheclean começa a excluir arquivos da partição do cache, o que leva mais algumas horas. (Um problema semelhante foi levantado na lista de discussão do Apache em 2009, sem uma solução: link )

O alto IOwait leva a problemas com a estabilidade do servidor da web (a ponte para o servidor de back-end do Tomcat às vezes fica paralisada).

Eu criei meu próprio script de remoção, que remove arquivos e diretórios de subdiretórios aleatórios do cache. Apenas para descobrir que a taxa de exclusão do script é apenas ligeiramente superior à taxa de crescimento do cache . O script leva ~ 10 segundos para ler o subdiretório a (por exemplo, / htcache / B / x) e libera cerca de 5 MB de espaço em disco. Nesses 10 segundos, o cache cresceu em mais 2 MB . Tal como acontece com o htcacheclean, o IOwait aumenta para 25% quando executa o script de remoção continuamente.

Alguma ideia?

  • Este é um problema específico do armazenamento iSCSI (bastante lento)?

  • Devo escolher um sistema de arquivos diferente para um disk_cache enorme? ext2? ext4?

  • Existe alguma otimização de parâmetro do kernel para esse tipo de cenário? (Eu já tentei o scheduler de prazo e um read_ahead_kb menor, sem efeito).

por flight 12.10.2011 / 13:04

2 respostas

2

10 segundos para leitura dir parece que você não está usando dir_index

verifique com

/sbin/tune2fs /dev/wherever | grep dir_index

como ativar

tune2fs -O dir_index /dev/wherever

mas isso afetará apenas os diretórios recém-criados, para reindexar tudo que for executado

e2fsck -D -f /dev/wherever
    
por 08.07.2012 / 21:24
2

através de minhas investigações recentes, desencadeadas por problemas semelhantes com htcacheclean, concluí que o principal problema com a limpeza de caches grandes ou profundos, especialmente aqueles que envolvem cabeçalhos Vary, é um problema com o design do próprio utilitário.

com base em procurar no código-fonte e observar a saída de strace -e trace = unlink, a abordagem geral parece ser a seguinte:

  1. iterar em todos os diretórios de nível superior (/ htcache / B / x /, acima)
    • exclua quaisquer arquivos .header e .data para entradas já expiradas
    • reúna os metadados para todas as entradas aninhadas (/htcache/B/x/i_iGfmmHhxJRheg8NHcQ.header.vary/A/W/oGX3MAV3q0bWl30YmA_A.header, acima)
  2. iterar todos os metadados de entrada aninhada e eliminar aqueles com tempo de resposta, modificador .header ou mod .data no futuro
  3. iterar todos os metadados de entrada aninhada e eliminar aqueles que expiraram
  4. iterar todos os metadados de entrada aninhados para encontrar o mais antigo; limpe-o; repita

e qualquer um dos últimos três passos retornará da sub-rotina de limpeza quando o tamanho do cache cair abaixo do limite definido.

Portanto, com um cache de crescimento rápido e / ou grande, a taxa de crescimento durante o tempo estendido necessário para a etapa 1 pode ser facilmente insuperável mesmo depois que você progredir para as etapas # 2- # 4.

agravando ainda mais o problema, se você ainda não tiver satisfeito os limites de tamanho até o final da etapa 2, o fato de ter que percorrer todos os metadados das entradas aninhadas para localizar as mais antigas, para somente exclua essa entrada única e faça a mesma coisa novamente, o que significa que o cache pode crescer novamente mais rápido do que você conseguirá cortar.

/* 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);
}

a solução?

obviamente discos rápidos (er) ajudariam. mas não está claro para mim quanto de um aumento na produção de IO seria necessário para superar os problemas inerentes à abordagem atual adotada pelo htcacheclean. nenhuma escavação contra os criadores ou mantenedores, mas com certeza parece que esse design não foi testado ou nunca esperado ter um bom desempenho contra caches amplos, profundos e de rápido crescimento.

mas o que parece funcionar, e eu ainda estou confirmando agora, é acionar o htcacheclean de dentro de um script bash que ele próprio passa pelos diretórios de nível superior.

#!/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;

Basicamente, essa abordagem permite que você chegue às etapas de eliminação (# 2- # 4) com muito mais rapidez e frequência, mesmo que apenas para um pequeno subconjunto de entradas. Isso significa que você tem uma chance de eliminar conteúdo a uma taxa mais rápida do que está sendo adicionada ao cache. novamente, parece estar funcionando para nós, mas eu só testei por alguns dias. e nossos alvos e crescimento de cache parecem estar no mesmo nível do seu, mas, no final das contas, sua milhagem pode variar.

é claro que o ponto principal deste post é que talvez seja útil para alguém que se depara com esta questão da mesma forma que eu fiz.

    
por 03.10.2013 / 04:40