HeadlinesBriefing HeadlinesBriefing.com

Melhor reutilização de conexões HTTP/1 em Go

Hacker News •
×

Considere esta função, que envia uma requisição GET para uma URL e retorna o código de status HTTP. Usando HTTP/1 (GODEBUG=http2client=0), chamá-la 100 vezes contra index.golang.org leva cerca de 710 milissegundos no Go 1.26 na máquina do autor. No Go 1.27, o mesmo programa leva cerca de 150 milissegundos, quase 5 vezes mais rápido.

A diferença vem do custo de estabelecer conexões. Fazer uma requisição por uma conexão nova exige um handshake TCP (1 tempo de ida e volta, ou RTT), um handshake TLS (2 RTT no TLS 1.2) e então a própria requisição HTTP, totalizando cerca de 3 RTT. Em comunicações entre regiões, as latências de ida costumam chegar a 50 ms ou mais, então apenas a configuração pode custar cerca de 300 ms. Mesmo com index.golang.org, que usa TLS 1.3 e oferece latência relativamente baixa, abrir uma conexão nova continua muito perceptível.

Para evitar esse custo, clientes e servidores HTTP tentam reutilizar conexões. Clientes e servidores HTTP/1.0 ativam isso com um cabeçalho Connection: keep-alive, enquanto conexões HTTP/1.1 são persistentes por padrão. O HTTP/2 multiplexa várias requisições e respostas em uma única conexão TCP.

No entanto, a reutilização pode falhar no HTTP/1. As respostas na mesma conexão são enviadas sequencialmente, então o net/http só consegue localizar o início da próxima resposta depois que o corpo da resposta atual for lido até o fim. No exemplo, o corpo da resposta nunca é lido, então, ao chamar resp.Body.Close, o net/http encontra um corpo não lido e não pode reutilizar a conexão com segurança. Até o Go 1.26, isso forçava uma nova conexão para cada requisição.

Fonte: Hacker News · Resumido por HeadlinesBriefing