Nginx request_time mais lento com HTTP / 2

2

Estamos executando o nginx / 1.9.10 como um servidor front-end com vários servidores de aplicativos como upstream. Estamos usando http simples, principalmente https e mudou para http / 2 no último fraco.

Estamos registrando assim:

 log_format custom '$host $server_port $request_time '
                   '$upstream_response_time $remote_addr '
                   '"$http2" $upstream_addr $time_iso8601 '
                   '"$request" $status $body_bytes_sent '
                   '"$http_referer" "$http_user_agent"';

De repente, vemos uma diferença maior entre $ request_time e $ upstream_response_time. Uma diferença aqui é bastante natural, pois o $ request_time depende da rede de usuários, enquanto o upstream_response_time não.

Normalmente, você não deve se importar muito com $ request_time, desde que $ upstream_response_time seja estável.

Mas eu ainda queria checar o que está acontecendo porque a situação piorava com http / 2. Então, eu comparava os tempos médios de resposta para https / 1.1 e https / 2.0

Primeiramente eu selecionei todas as solicitações http / 1.1 e calculei a média de response_time e a média upstream_time:

grep ' 443 ' access.log|grep 'HTTP/1.1'|\ 
cut -d ' ' -f 3,4 | awk '{r+=$1; u+=$2} END {print r/NR; print u/NR}'

0.0139158  # average response time for https/1.1
0.00691421 # average upstream time for https/1.1

Agora fiz o mesmo com https / 2.0:

grep ' 443 ' access.log|grep 'HTTP/2.0'| \
cut -d ' ' -f 3,4 | awk '{r+=$1; u+=$2} END {print r/NR; print u/NR}'
0.0828755  # average response time for https/1.1
0.00606643 # average upstream time for https/2.0

Como você vê, o tempo de envio é quase idêntico, mas o tempo de solicitação é mais lento para http / 2 pelo fator 7! Uau! Não é esperado que http / 2 seja mais rápido?

Agora eu verifiquei todos os pedidos que têm uma enorme diferença entre esses dois valores e quase todos os top 500 foram um código de status de 302

grep ' 443 ' access.log | grep 'HTTP/1.1' | \
awk '{ if ( $3 != $4 && $4 != "-" ) { \
  gsub(/\./,"",$3);gsub(/\./,"",$4); \
  print $3-$4,$4,$6,$9,$11,$12 }}' | \
sort -n | tail -n 10000 | grep 'POST HTTP/1.1" 302' | wc -l

9008 
# of 10000 (or 90%) request ordered by difference between 
# response and request time have status code 302  

Portanto, 90% de todos os pedidos com a maior diferença entre a resposta e o tempo de envio são o código de status 302. Isso é estranho

Em http / 2, é ainda pior:

grep ' 443 ' access.log | grep 'HTTP/2.0' | \
awk '{ if ( $3 != $4 && $4 != "-" ) { \
  gsub(/\./,"",$3);gsub(/\./,"",$4); \
  print $3-$4,$4,$6,$9,$11,$12 }}' | \
sort -n | tail -n 10000 | grep 'POST HTTP/2.0" 302' | wc -l

9790
# of 10000 (or 98%) request ordered by difference between 
# response and request time have status code 302  

Então, aqui estão 98% desses pedidos são 302 status.

Por que o http / 2 parece ser mais lento que o http / 1.1? Por que tantos códigos de status 302 envolvidos em solicitações foram upstream e o tempo de resposta é muito diferente (em HTTP / 1.1 e HTTP / 2.0)?

    
por Janning 19.02.2016 / 16:04

1 resposta

0

Gostei muito da missão e analisei.

Eu peguei esses recursos principalmente: [ link ] [ link ] [ link ] [ link ] e este PDF

Você provavelmente baixou o nginx / 1.9.10 do link do Nginx.org. Por favor confirme. Você construiu a partir da fonte? Você já tentou o nginx / 1.9.12?

Como você pode ver no artigo da CloudFlare, quando o Average Page Load time HTTP / 2 medido é claramente o vencedor (pelo menos para o seu site).

Access via HTTP Protocol Version    Average Page Load time
HTTP 1.x                            9.07 sec.
SPDY/3.1                            7.06 sec.
HTTP/2                              4.27 sec. 

No entanto, ao acompanhar o tempo médio de resposta, confira o segundo artigo do Nginx.org que defini como uma referência onde se lê:

The next key point of HTTP/2 is multiplexing. Instead of sending and receiving responses and requests as separate streams of data over multiple connections, HTTP/2 multiplexes them over one stream of bytes or one stream of data. It slices data for different requests and for different responses, and each slice has its own identification and its size field, which is there so the endpoint can determine which data belongs to which request.

The disadvantage here is that since each chunk of data has its own identification, its own fields, there's some metadata that transfers in addition to the actual data. So, it has some overhead.

Os outros problemas podem estar relacionados à sua configuração nginx, por exemplo, dentro do bloco do servidor.

    
por 06.03.2016 / 03:05