Problema muito lento no Sidekiq com fila grande devido a enorme quantidade de notificações de usuário não lidas

Então, estou com um problema com o Sidekiq.

Ele executa as tarefas incrivelmente rápido quando monitorado pela interface web do Sidekiq. Mas ocasionalmente parece ficar sobrecarregado e começa a rodar extremamente lento. Rodando a cerca de 1-5% da sua velocidade normal e não se recupera a menos que eu limpe o Redis, apesar do uso de recursos do servidor estar normal/baixo.

Parece que, assim que a fila atinge um certo tamanho, ela trava e fica drasticamente mais lenta. Fazendo a fila crescer ainda mais. Estou apenas chutando aqui, talvez a fila esteja grande apenas porque ela está ficando lenta por algum outro motivo.

Este gif descreve como isso parece para mim.

Há muitos recursos de servidor disponíveis, o uso de CPU está muito baixo agora - abaixo de 10%. Há muita RAM e SSD disponíveis também. Sobre o servidor, ele tem 16 núcleos de CPU com 32 threads. Tentei rodar entre 8-14 unicorn_sidekiqs. Também tentei 20, mas isso criou muitos erros 5xx.

Consegui acelerar as tarefas lentas exibidas na aba ‘busy’ da interface web do Sidekiq usando
Could sidekiq queue be reason for 500 errors? - #30 by bartv (
adicionando ‘vm.overcommit_memory = 1’ ao arquivo /etc/sysctl.conf e reiniciando) e também reduzindo os unicorn_sidekiqs para 8 (de 12).

Ainda está rodando lento, no entanto. Vi isso no log do Redis ontem (o único outro aviso era sobre não ter o overcommit_memory definido como 1, o que modifiquei acima):

# WARNING: /proc/sys/net/core/somaxconn está definido para o valor mais baixo de 128

^ Alguém já corrigiu esse aviso acima?

De qualquer forma, se alguém tiver ideias sobre qual poderia ser a causa e/ou a solução - por favor, me avise. Agradeceria muito.

Seria ótimo resolver esse problema para que não aconteça novamente, em vez de apenas limpar.

Aqui está uma captura de tela do que estou vendo no painel do Sidekiq:

E algumas capturas de tela das tarefas na aba busy:

Além disso, alguém sabe se é seguro usar essa opção? Excluir a fila de baixa prioridade da interface web do Sidekiq?

Atualização: excluí a fila de baixa prioridade sem problemas, no entanto, a velocidade de processamento dos trabalhos permaneceu a mesma.

Você tem métricas sobre quanto tempo seus jobs estão levando? Parece que há uma grande quantidade de contenção nos seus jobs PostAlert, mas outros são concluídos rapidamente.

Pelo que observei na interface web do Sidekiq. Sim, você está certo, outras tarefas parecem ser concluídas rapidamente, com exceção de:

Jobs::PostAlert - de 0 a 3 minutos, com a maioria na faixa de 0 a 1 minuto.
Jobs::ProcessPost - de 0 a 21 segundos.

Seu servidor SMTP está lento?

Estou usando o Amazon SES para envio e também configurei o receptor de e-mail para receber VERP.

O limite de envio exibido no SES é de 25 e-mails por segundo. Isso é muito lento? Provavelmente posso solicitar um aumento.

Agora que você mencionou, notei uma correlação com esse problema começando em um dia em que uma quantidade maior que o normal de e-mails de resumo foi enviada (muitos e-mails de resumo foram consolidados em um único dia devido a um problema de configuração no passado).

Quantos usuários você está enviando e-mails? Como se apresentam os volumes de e-mail?

Não tenho certeza sobre quantos usuários estão recebendo e-mails. A estatística de usuários ativos nos últimos 30 dias no painel administrativo é de 60,8 mil; talvez isso seja um indicador? Aqui estão as estatísticas de envio do SES (limite de 100 mil+ em 24 horas):

Atualização: O limite de envio por segundo do SES foi aumentado de 25 para 50. Agora é possível enviar a uma velocidade de 180 mil e-mails por hora (embora o total permitido por dia seja pouco mais de 100 mil). No entanto, a velocidade de processamento das tarefas do Sidekiq não parece ter melhorado.

Tivemos um problema há alguns anos em que usuários com 10 mil notificações não lidas tornavam as consultas de notificações lentas e, consequentemente, o trabalho PostAlert também ficava lento.

Adicionamos uma proteção para que isso não aconteça mais com tanta frequência, mas pode apresentar características de desempenho diferentes no seu ambiente.

Você tem usuários configurados para acompanhar categorias que ignoram a contagem de notificações?

Você pode verificar o número máximo de notificações não lidas por usuário no seu banco de dados?

Então, limpei a fila de baixa prioridade mais uma vez e a deixei por alguns dias (sem alterações desde minha última atualização) - não acelerou imediatamente e os jobs enfileirados começaram a se acumular rapidamente, mas parece que se resolveu sozinho com o tempo. O processamento dos jobs está extremamente rápido agora. :slight_smile: Com um intervalo de polling de 20s, vi uma faixa de 55 a 140 jobs por segundo nos últimos minutos. Por dia, também parece saudável, sem acúmulo na fila.

Muito obrigado pela ajuda @Falco @supermathie @Stephen, realmente apreciei!

Quanto às suas perguntas, não tenho certeza de como verificar isso. Ficarei feliz em verificar (precisaria de alguma orientação) e fornecer as informações se ainda for útil. Algo possivelmente relevante é que tenho a configuração ‘máximo de e-mails por dia por usuário’ definida como 3 há muito tempo.

Talvez eu tenha falado cedo demais. Os jobs do Sidekiq estão sendo executados atualmente a uma taxa de ~1 a 3 por segundo, com uma fila de 8,81 milhões.

:philosoraptor:

Quando foi a sua última atualização? Adicionei algumas melhorias de desempenho ao trabalho PostAlert há alguns dias:

Alguns dos nossos sites muito grandes estavam apresentando problemas de desempenho em categorias com muitas pessoas “assistindo à primeira publicação”. Este commit resolveu o problema em nossa hospedagem, então há uma chance de que possa ajudar seu site também.

Ótimo! Estou atualizando agora. A última atualização foi há cerca de 10 dias (tests-passed). Vou monitorar e ver se há alguma melhoria, depois retorno com um relatório. Obrigado!

Atualização: Infelizmente, não houve melhorias imediatas na velocidade desde a atualização. Vamos ver se melhora com o tempo.

Atualização: Ainda está rodando lento e a fila está aumentando. Vejo muitos processos postmaster via ‘top’. Uso total de CPU de ~85% (32 núcleos), sendo a grande maioria proveniente do postmaster. O que é interessante, pois mais cedo hoje o uso de CPU era de 20-35% (o sidekiq também estava lento naquela época). Relacionado: Primary Postgres database process (postmaster) eating all CPU - #5 by pfaffman

Acha que esses avisos do Redis podem ter algo a ver com isso? Eles são exibidos durante a reconstrução do app:

# AVISO: A configuração de backlog TCP de 511 não pode ser aplicada porque /proc/sys/net/core/somaxconn está definido para o valor menor de 128.

# AVISO: Você tem o suporte a Transparent Huge Pages (THP) habilitado no seu kernel. Isso causará problemas de latência e uso de memória com o Redis. Para corrigir esse problema, execute o comando 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' como root e adicione-o ao seu /etc/rc.local para manter a configuração após uma reinicialização. O Redis deve ser reiniciado após a desabilitação do THP.

Alguém já corrigiu esses erros em uma instalação com Docker?

Eu já adicionei vm.overcommit_memory = 1 ao /etc/sysctl.conf para corrigir o aviso de overcommit de memória.

Então, corrigi o aviso sobre Transparent Huge Pages (THP) apenas executando echo never > /sys/kernel/mm/transparent_hugepage/enabled como root. Ainda não adicionei isso ao rc.local para persistência, apenas para testes. Fiz uma reconstrução do Discourse e o desempenho ficou mais ou menos o mesmo — talvez uma leve melhoria.

Ainda não tenho certeza de como corrigir este aviso:
# AVISO: A configuração de TCP backlog de 511 não pode ser aplicada porque /proc/sys/net/core/somaxconn está definido para o valor menor de 128.

Vi algumas pessoas dizendo que o Docker ainda usará o valor 128, mesmo que o valor do sistema seja definido para algo maior, ou seja, através de um guia como este: Performance tips for Redis Cache Server – Tech and Me

Estou pensando que poderia ser uma boa ideia atribuir alguns UNICORN_SIDEKIQs especificamente à fila de baixa prioridade.

Parece que as tarefas de prioridade ‘padrão’, ou seja, PostAlert, estão avançando bastante devagar e, assim que há um acúmulo dessas tarefas lentas de prioridade padrão, a fila de baixa prioridade (com tarefas que poderiam ser concluídas a uma taxa significativamente mais rápida) cresce descontroladamente, já que quase nenhuma delas parece ser concluída. Estou suspeitando que esse crescimento descontrolado torna o processamento geral de todas as tarefas mais lento. Acredito que isso possa explicar também a grande flutuação em trabalhos por segundo.

Alguém sabe se é possível atribuir UNICORN_SIDEKIQs no arquivo app.yml (ou de alguma outra forma) a tarefas de prioridade específica?

Adicionar mais Sidekiqs enquanto seu banco de dados é um gargalo só vai piorar a situação.

Como disse acima, você precisa depurar o problema de desempenho ruim do PostgreSQL.