Threads virtuais
O custo do modelo de uma thread por requisição, a concorrência estruturada e o que ainda bloqueia.
Threads virtuais: concorrência sem pool
Um servidor Java clássico trata cada requisição em uma thread retirada de um pool. Essa thread é uma thread do sistema operacional: custa cerca de um megabyte de pilha reservada, sua criação leva centenas de microssegundos e o kernel precisa escaloná-la. Por isso mantemos poucas — duzentas, quatrocentas — e as reciclamos. Mas o que essa thread faz durante a requisição? Ela espera. Espera o PostgreSQL por oito milissegundos, depois um serviço HTTP de terceiros por cem, depois o Redis. Em uma requisição de cento e cinquenta milissegundos, o processador talvez trabalhe três milissegundos. No resto do tempo, um recurso raro e caro fica imobilizado sem fazer nada.
Quando a carga ultrapassa o tamanho do pool, as requisições se acumulam em uma fila. O tempo de resposta desaba enquanto os processadores estão com dez por cento de utilização. A resposta habitual a esse muro é migrar para a programação reativa: sem bloqueio, com callbacks, CompletableFuture ou fluxos reativos. Isso funciona, e custa caro — o código se inverte, as pilhas de chamadas se tornam inutilizáveis, o depurador deixa de acompanhar, e toda a cadeia precisa se tornar não bloqueante, sob pena de perder todo o benefício. As threads virtuais, estabilizadas no Java 21, propõem manter o código bloqueante, sequencial e legível, tornando a própria thread quase gratuita.
Comentários
Os comentários são alimentados pelo GitHub Discussions
Conecte-se com o GitHub para participar da discussão