A partir do sgcWebSockets 2024.2.0, o servidor HTTP/2 foi aprimorado no recebimento de requisições HTTP/2. Agora, por padrão, quando o servidor recebe uma nova requisição HTTP/2, ela é enfileirada e despachada por uma das threads do Pool de Threads. Isso evita o problema de quando várias requisições são enviadas pela mesma conexão e processadas sequencialmente.
Veja abaixo as diferenças entre HTTP 1.1 e HTTP 2.0:
HTTP 1.1
No comportamento HTTP tradicional, ao fazer múltiplas requisições pela mesma conexão, o cliente precisa aguardar a resposta de cada requisição antes de enviar a próxima. Essa abordagem sequencial aumenta significativamente o tempo de carregamento dos recursos de um site. Para resolver esse problema, o HTTP/1.1 introduziu um recurso chamado pipelining, que permite ao cliente enviar múltiplas requisições sem aguardar as respostas do servidor. O servidor, por sua vez, responde ao cliente na mesma ordem em que recebeu as requisições.
Embora o pipelining parecesse uma solução, ele enfrentou desafios:
- Ignorância do servidor ou corrupção de resposta: Alguns servidores ignoravam as requisições em pipeline ou corrompiam as respostas, levando a uma comunicação não confiável.
- Bloqueio de cabeça de fila (Head-of-Line Blocking): A primeira requisição no pipeline poderia bloquear as subsequentes, causando atrasos no processamento das demais. Esse fenômeno, conhecido como head-of-line blocking, resultava em tempos de carregamento de página mais lentos.
Em um esforço para otimizar o carregamento de páginas em servidores que suportam HTTP/1.1, os navegadores implementaram uma solução alternativa: abrir de seis a oito conexões paralelas com o servidor, permitindo a transmissão simultânea de múltiplas requisições. Esse paralelismo visa mitigar os problemas associados ao pipelining e melhorar os tempos gerais de carregamento de página.
A escolha de seis a oito conexões paralelas pelos navegadores é baseada em considerações de otimização. As razões específicas por trás dessa escolha podem envolver um equilíbrio entre utilização de recursos, eficiência de rede e evitar possíveis gargalos.
HTTP 2.0
Em resposta às limitações encontradas no pipelining, o HTTP/2 introduziu um recurso chamado multiplexação. A multiplexação permite uma comunicação mais eficiente entre cliente e servidor ao possibilitar a transmissão concorrente de múltiplas requisições e respostas em uma única conexão.
O HTTP/2 utiliza um mecanismo de enquadramento binário, o que significa que as mensagens HTTP são fragmentadas em unidades menores e independentes chamadas frames. Esses frames podem ser intercalados e enviados pela conexão de forma independente entre si. No receptor, os frames são reagrupados para reconstruir a mensagem HTTP original.
Esse mecanismo de enquadramento binário é fundamental para alcançar a multiplexação no HTTP/2. Ele permite que o navegador envie múltiplas requisições pela mesma conexão sem encontrar problemas de bloqueio. Como resultado, navegadores como o Chrome utilizam o mesmo ID de conexão para requisições HTTP/2, permitindo uma comunicação eficiente e ininterrupta entre cliente e servidor.
Em essência, o recurso de multiplexação do HTTP/2, habilitado pelo mecanismo de enquadramento binário, aumenta a eficiência e a velocidade da troca de dados entre clientes e servidores ao facilitar a transmissão concorrente de múltiplas requisições e respostas em uma única conexão.
Componente TsgcWebSocketHTTPServer
Para melhorar o desempenho do protocolo HTTP/2, as requisições são despachadas por padrão em um Pool de Threads (por padrão 32) cada vez que uma nova requisição HTTP/2 é recebida pelo servidor. Isso evita esperas quando uma única conexão envia muitas requisições concorrentes, que de outra forma exigiriam processamento sequencial (no contexto da thread de conexão) sem este pool de threads.
O comportamento do PoolOfThreads pode ser configurado nas seguintes propriedades.
- HTTP2Options.PoolOfThreads.Enabled: (por padrão true) habilita o despacho das requisições HTTP/2 no pool de threads em vez da thread de conexão.
- HTTP2Options.Threads: (por padrão 32) o número de threads usadas para tratar as requisições HTTP/2. Defina um número de acordo com o número de processadores do seu servidor.
Para ajuste fino das requisições, selecionando quais devem ser processadas no Pool de Threads (por serem demoradas) enquanto outras podem ser processadas na thread de conexão, use o evento OnHttp2BeforeAsyncRequest. Este evento é acionado antes de enfileirar a requisição no pool de threads; use o parâmetro Async para definir se a requisição é assíncrona ou não.
procedure OnHTTP2BeforeAsyncRequest(Sender: TObject; Connection: TsgcWSConnection; const ARequestInfo: TIdHTTPRequestInfo; var Async: Boolean);
begin
if ARequestInfo.Document = '/time-consuming-request' then
ASync := False;
end;
