
executamos nosso sistema Java há mais de 2 anos sem nunca travar o sistema. Temos 2 servidores físicos executando software Java semelhante (2 JVMs em cada servidor) para formar um cluster. Pelo que posso dizer, o travamento só começou a acontecer quando introduzimos core pinning e mappedbus.io para acesso à memória compartilhada entre 2 JVMs em um dos servidores. O travamento do sistema aconteceu apenas 4 vezes em 2 semanas e só acontece na máquina onde configuramos a fixação do núcleo e o acesso aos arquivos mapeados na memória entre as JVMs. Desativamos essa configuração, portanto, não fixamos os núcleos para girar na leitura dos arquivos mapeados na memória e não fixamos nosso thread de aplicativo principal. Observe que, quando digo fixar, também estamos ocupados girando o thread em execução naquele núcleo fixado.
Isso é totalmente anedótico. Como o sistema não trava todos os dias, não posso dizer com certeza se isso tem alguma coisa a ver com fixação de núcleo ou acesso à memória compartilhada. No entanto, com a fixação (e rotação ocupada) desativada e o acesso à memória compartilhada em um loop com LockSupport.parkNanos(5000) parece que não temos nenhum travamento do sistema.
A latência é crítica para nós, portanto, essa configuração "não ocupada" é apenas uma solução temporária.
Além disso, observe que movi o aplicativo para um servidor idêntico e também pude experimentar esse travamento completo do sistema. Portanto, não consigo ver isso como uma falha de hardware.
Então, ao pesquisar os logs antes ou depois de uma falha, isso é o que parece ser relevante para mim. Existem várias dessas pilhas. Estou apenas postando o primeiro aqui (ou seja, não acredito que isso tenha algo a ver com o próprio postgres)
kernel: [25738.874778] INFO: task postgres:2155 blocked for more than 120 seconds.
kernel: [25738.874833] Not tainted 5.4.0-050400-generic #201911242031
kernel: [25738.874878] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
kernel: [25738.874928] postgres D 0 2155 2056 0x00004000
kernel: [25738.874931] Call Trace:
kernel: [25738.874942] __schedule+0x2e3/0x740
kernel: [25738.874948] ? __wake_up_common_lock+0x8a/0xc0
kernel: [25738.874951] schedule+0x42/0xb0
kernel: [25738.874957] jbd2_log_wait_commit+0xaf/0x120
kernel: [25738.874961] ? wait_woken+0x80/0x80
kernel: [25738.874965] jbd2_complete_transaction+0x5c/0x90
kernel: [25738.874969] ext4_sync_file+0x38c/0x3e0
kernel: [25738.874974] vfs_fsync_range+0x49/0x80
kernel: [25738.874977] do_fsync+0x3d/0x70
kernel: [25738.874980] __x64_sys_fsync+0x14/0x20
kernel: [25738.874985] do_syscall_64+0x57/0x190
kernel: [25738.874991] entry_SYSCALL_64_after_hwframe+0x44/0xa9
kernel: [25738.874993] RIP: 0033:0x7f96dc24b214
kernel: [25738.875002] Code: Bad RIP value.
kernel: [25738.875003] RSP: 002b:00007fffb2abd868 EFLAGS: 00000246 ORIG_RAX: 000000000000004a
kernel: [25738.875006] RAX: ffffffffffffffda RBX: 00007fffb2abd874 RCX: 00007f96dc24b214
kernel: [25738.875007] RDX: 00005635889ba238 RSI: 00005635889a1490 RDI: 0000000000000003
kernel: [25738.875009] RBP: 00007fffb2abd930 R08: 00005635889a1480 R09: 00007f96cc1e1200
kernel: [25738.875010] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
kernel: [25738.875011] R13: 0000000000000000 R14: 000056358899c5a0 R15: 0000000000000001
ps isso aconteceu em 16.04 e no kernel 4.15 também. A atualização para 18.04 e 5.0 foi uma tentativa de resolver o travamento do sistema, mas não fez nenhuma diferença.
A outra coisa que considerei é que talvez esse traço seja apenas um sintoma, não o problema. Ou seja, meu aplicativo conectou o servidor e fez com que outros processos fossem bloqueados no io e recebessem esses erros. Mas como o servidor congela completamente, não tenho como saber o estado da minha aplicação naquele momento.
Informações adicionais em resposta aos comentários
Primeiro, apenas para reiterar, não tenho evidências sólidas de que a fixação central + memória compartilhada seja a gota d'água que quebra as costas do camelo, mas este é meu melhor palpite com base no histórico de alterações e interrupções.
O modelo de CPU é Intel(R) Xeon(R) CPU E5-2620 v4 a 2,10 GHz com turbo boost. Existem 2 destes no servidor. Estou fixando os números de CPU 2,4,6, que acredito estarem na mesma CPU física. O hiperthreading está ativado.
A configuração é assim. JVM-A tem um thread de spin ocupado fixado gravando no arquivo mapeado na memória X e lendo do arquivo mapeado na memória Y. JVM-B tem um thread de spin ocupado fixado lendo do arquivo mapeado na memória X e gravando de volta no arquivo mapeado na memória Y. Na JVM- B, o thread de leitura fixado publica a mensagem em um buffer de anel disruptor com um trabalhador giratório ocupado fixado. A mensagem é uma instrução de ordem que é finalmente enviada ao mercado para este trabalhador. Esta é uma plataforma de negociação de baixa latência.
Esta postagem oferece uma exploração melhor de LockSupport.parkNanos do que posso aquihttps://hazelcast.com/blog/locksupport-parknanos-under-the-hood-and-the-curious-case-of-parking/
Tenho 2 HDD de 10.000 rpm em RAID 1 com controlador RAID incorporado.
Em relação à latência alvo, sim, poderíamos, em teoria, mesclar as duas JVMs em uma e nos livrar completamente desse canal de arquivo mapeado na memória. No entanto, há outras considerações antes de fazer isso, então gostaria de me concentrar primeiro na compreensão desse problema técnico.
Finalmente, o postgres neste servidor está sendo executado apenas no modo de recuperação, não é o principal. Além disso, nosso sistema não realiza muita E/S de banco de dados. Na verdade, ele é usado apenas para inicializar e começar o dia, e persistir a atividade de negociação do dia durante a noite. Uma das falhas ocorreu em um momento em que não haveria quase nenhuma E/S no banco de dados.
Responder1
"Bloqueado", no caso de hung_task_timeout_secs
significa que uma tarefa esteve no estado ininterrupto D por tanto tempo. 120 segundos é uma quantidade extraordinária de tempo para realizar E/S.
Comece o monitoramento que pode obter métricas deste host.dados de redeé bom para isso, pois coleta muitas coisas a cada segundo na memória, portanto, não há muita E/S de disco. E tem bons gráficos.
Revise a latência do disco, como com arquivos iostat -xz 1
. Esperas acima de ms de um dígito não são boas. Compartilhe o que é esse armazenamento, fusos, estado sólido, SAN LUNs.
Em relação à rotação e fixação, suspeito que você esteja forçando o agendador a morrer de fome. Compartilhe o modelo específico de CPU em questão e quais núcleos você está fixando para fazer o quê. Como é LockSupport.parkNanos()
implementado?
Análise vmstat 1
. Ter constantemente muitas tarefas em execução r
ou b
em estado ininterrupto não é bom.
Considere instalar o BPF e usar scripts para coletar diagnósticos de tarefas.runqslower
mostrará tarefas em espera acima de um determinado limite. Muito rápido é o ideal, observe que as unidades de limite são microssegundos.
Recuando um minuto, considere o design desta coisa.
Qual é exatamente a meta de latência, fazendo o quê e com que rapidez?
Existe uma razão pela qual o postgres está sendo executado no mesmo host? Se fosse remoto e acessado via TCP, sua E/S não seria um problema para a aplicação JVM.
Responder2
Ok, então no final o problema era bem simples. Meu teste isolado nunca conseguiu travar a máquina porque estava faltando esse elemento em meu código de teste. O problema não tem nada a ver com memória compartilhada ou fixação de núcleo em si. Acontece que o isolamento dos núcleos reduziu ligeiramente o recurso compartilhado disponível a ponto de o agendador poder morrer de fome, porque ...
Ambas as JVMs foram definidas com prioridade em tempo real usando
sudo renice -n -20 $!
sudo chrt -r -a -p 99 $!
Toda a JVM foi atingida, totalizando quase 300 threads com prioridade máxima. Troca de contexto acima de 150.000/s, mesmo com utilização relativamente baixa da CPU.
Deixamos a gentileza e removemos a mudança em tempo real. Isso parece ter resolvido o problema. O objetivo original da configuração RT legada pode ser alcançado alterando a forma como movimentamos/fixamos/estados-c/estados-p, etc.