Tivemos um pequeno problema de failover com uma de nossas VMs HAProxy hoje. Quando investigamos, descobrimos o seguinte:
26 de janeiro 07:41:45 kernel haproxy2: [226818.070059] __ratelimit: 10 retornos de chamada suprimidos 26 de janeiro 07:41:45 kernel haproxy2: [226818.070064] Sem memória de soquete 26 de janeiro 07:41:47 kernel haproxy2: [226819.560048] Sem memória de soquete 26 de janeiro 07:41:49 kernel haproxy2: [226822.030044] Sem memória de soquete
O que, poresse link, aparentemente tem a ver com configurações padrão baixas para net.ipv4.tcp_mem
. Então, nós os aumentamos em 4x em relação aos padrões (este é o Ubuntu Server, não tenho certeza se o sabor do Linux é importante):
os valores atuais são: 45984 61312 91968 os novos valores são: 183936 245248 367872
Depois disso, começamos a ver uma mensagem de erro bizarra:
26 de janeiro 08:18:49 kernel haproxy1: [2291.579726] Cadeia de hash de rota muito longa! 26 de janeiro 08:18:49 kernel haproxy1: [2291.579732] Ajuste seu secret_interval!
Shh..é um segredo!!
Aparentemente, isso tem a ver com /proc/sys/net/ipv4/route/secret_interval
o padrão 600 e os controleslimpeza periódica do cache de rota
O
secret_interval
instrui o kernel com que frequência eliminar TODAS as entradas de hash de rota, independentemente de quão novas/antigas elas sejam. Em nosso ambiente, isso geralmente é ruim. A CPU estará ocupada reconstruindo milhares de entradas por segundo sempre que o cache for limpo. No entanto, configuramos isso para ser executado uma vez por dia para evitar vazamentos de memória (embora nunca tenhamos tido um).
Embora estejamos felizes em reduzir isso,parece estranho recomendar descartar todo o cache de rota em intervalos regulares, em vez de simplesmente retirar os valores antigos do cache de rota com mais rapidez.
Após alguma investigação, descobrimos /proc/sys/net/ipv4/route/gc_elasticity
qual parece ser a melhor opção para manter o tamanho da tabela de rotas sob controle:
gc_elasticity
pode ser melhor descrito como a profundidade média do bucket que o kernel aceitará antes de começar a expirar as entradas de hash de rota. Isso ajudará a manter o limite superior de rotas ativas.
Ajustamos a elasticidade de 8 para 4, na esperança de que o cache de rota se reduza de forma mais agressiva.Isso secret_interval
não parece correto para nós. Mas há um monte de configurações e não está claro qual é realmente o caminho certo a seguir aqui.
- /proc/sys/net/ipv4/route/gc_elasticity (8)
- /proc/sys/net/ipv4/route/gc_interval (60)
- /proc/sys/net/ipv4/route/gc_min_interval (0)
- /proc/sys/net/ipv4/route/gc_timeout (300)
- /proc/sys/net/ipv4/route/secret_interval (600)
- /proc/sys/net/ipv4/route/gc_thresh (?)
- rhash_entries (parâmetro do kernel, padrão desconhecido?)
Não queremos fazer o roteamento do Linuxpior, então temos medo de mexer em algumas dessas configurações.
Alguém pode aconselhar quais parâmetros de roteamento são melhores para ajustar, para uma instância HAProxy de alto tráfego?
Responder1
Nunca encontrei esse problema. No entanto, você provavelmente deve aumentar a largura da tabela hash para reduzir sua profundidade. Usando "dmesg", você verá quantas entradas possui atualmente:
$ dmesg | grep '^IP route'
IP route cache hash table entries: 32768 (order: 5, 131072 bytes)
Você pode alterar esse valor com o parâmetro de linha de comando de inicialização do kernel rhash_entries
. Primeiro experimente manualmente e depois adicione-o ao seu lilo.conf
arquivo ou grub.conf
.
Por exemplo:kernel vmlinux rhash_entries=131072
É possível que você tenha uma tabela de hash muito limitada porque atribuiu pouca memória à sua VM HAProxy (o tamanho do hash da rota é ajustado dependendo da RAM total).
Em relação a tcp_mem
, tenha cuidado. Suas configurações iniciais me fazem pensar que você estava rodando com 1 GB de RAM, 1/3 dos quais poderiam ser alocados para soquetes TCP. Agora você alocou 367.872 * 4.096 bytes = 1,5 GB de RAM para soquetes TCP. Você deve ter muito cuidado para não ficar sem memória. Uma regra prática é alocar 1/3 da memória para HAProxy e outro 1/3 para a pilha TCP e o último 1/3 para o resto do sistema.
Suspeito que sua mensagem "memória sem soquete" venha das configurações padrão em tcp_rmem
e tcp_wmem
. Por padrão você tem 64 kB alocados na saída para cada soquete e 87 kB na entrada. Isso significa um total de 300 kB para uma conexão proxy, apenas para buffers de soquete. Adicione a isso 16 ou 32 kB para HAProxy e você verá que com 1 GB de RAM você suportará apenas 3.000 conexões.
Ao alterar as configurações padrão de tcp_rmem
e tcp_wmem
(parâmetro intermediário), você pode diminuir muito a memória. Obtenho bons resultados com valores tão baixos quanto 4.096 para o buffer de gravação e 7.300 ou 16.060 pol. tcp_rmem
(5 ou 11 segmentos TCP). Você pode alterar essas configurações sem reiniciar, mas elas só serão aplicadas a novas conexões.
Se você preferir não tocar em seusysctlsdemais, o HAProxy mais recente, 1.4-dev8, permite ajustar esses parâmetros da configuração global e por lado (cliente ou servidor).
Espero que isso ajude!
Responder2
Muitas vezes é Out of socket memory error
enganoso. Na maioria das vezes, em servidores voltados para a Internet, isso acontecenãoindicar qualquer problema relacionado à falta de memória. Como expliquei com muito mais detalhes emuma postagem no blog, o motivo mais comum é o número de soquetes órfãos. Um soquete órfão é um soquete que não está associado a um descritor de arquivo. Em certas circunstâncias, o kernel emitirá o Out of socket memory error
mesmo que você esteja 2x ou 4x longe do limite ( /proc/sys/net/ipv4/tcp_max_orphans
). Isso acontece com frequência em serviços voltados para a Internet e é perfeitamente normal. O curso de ação correto neste caso é ajustar tcp_max_orphans
para pelo menos 4x o número de órfãos que você normalmente vê em seu pico de tráfego.
Não dê ouvidos a nenhum conselho que recomende afinação tcp_mem
ou tcp_rmem
ou tcp_wmem
a menos que vocêrealmentesabe o que você está fazendo. Aqueles que dão esses conselhos normalmente não o fazem. O vodu deles geralmente é errado ou inadequado para o seu ambiente e não resolverá o seu problema. Pode até piorar as coisas.
Responder3
Ajustamos alguns desses parâmetros regularmente. Nosso padrão para plataformas de negociação de alto rendimento e baixa latência é:
net.ipv4.tcp_rmem = 4096 16777216 33554432 net.ipv4.tcp_wmem = 4096 16777216 33554432 net.ipv4.tcp_mem = 4096 16777216 33554432 net.core.rmem_default = 16777216 net.core.wmem_default = 16777216 net.core.rmem_max=16777216 net.core.wmem_max=16777216 net.core.netdev_max_backlog=30000 net.core.netdev_max_backlog=30000