2015-01-07 13 views
7

Abbiamo un'app Web Node/express che sta servendo asset statici oltre al contenuto normale, tramite express.static(). C'è un server nginx davanti ad esso che è attualmente configurato su gzip queste richieste di risorse statiche, se lo user agent è attivo.Impossibile disattivare la codifica di trasferimento chunked in nginx con gzip per le risorse statiche servite dal backend Node

Tuttavia, anche se nginx sta facendo la gzip come previsto, si sta cadendo il Content-Length colpo di testa dalla provenienza, e l'impostazione Transfer-Encoding: chunked invece. Questa operazione interrompe la memorizzazione nella cache del nostro CDN.

Qui di seguito sono le risposte per una richiesta tipica risorsa statica (un file JS in questo caso), dal backend nodo e da nginx:

Richiesta:

curl -s -D - 'http://my_node_app/res/my_js.js' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Connection: keep-alive' --compressed -o /dev/null 

risposta intestazioni da Node:

HTTP/1.1 200 OK 
Accept-Ranges: bytes 
Date: Wed, 07 Jan 2015 02:24:55 GMT 
Cache-Control: public, max-age=0 
Last-Modified: Wed, 07 Jan 2015 01:12:05 GMT 
Content-Type: application/javascript 
Content-Length: 37386 // <--- The expected header 
Connection: keep-alive 

intestazioni di risposta da nginx:

HTTP/1.1 200 OK 
Server: nginx 
Date: Wed, 07 Jan 2015 02:24:55 GMT 
Content-Type: application/javascript 
Transfer-Encoding: chunked // <--- The problematic header 
Connection: keep-alive 
Vary: Accept-Encoding 
Cache-Control: public, max-age=0 
Last-Modified: Wed, 07 Jan 2015 01:12:05 GMT 
Content-Encoding: gzip 

La nostra attuale configurazione nginx per le attività statiche location si presenta come di seguito:

nginx config:

# cache file paths that start with /res/ 
location /res/ { 
    limit_except GET HEAD { } 

    # http://nginx.com/resources/admin-guide/caching/ 
    # http://nginx.org/en/docs/http/ngx_http_proxy_module.html 

    proxy_buffers 8 128k; 
    #proxy_buffer_size 256k; 
    #proxy_busy_buffers_size 256k; 

    # The cache depends on proxy buffers, and will not work if proxy_buffering is set to off. 
    proxy_buffering  on; 
    proxy_http_version 1.1; 
    proxy_set_header Connection ""; 
    proxy_connect_timeout 2s; 
    proxy_read_timeout 5s; 
    proxy_pass   http://node_backend; 

    chunked_transfer_encoding off; 

    proxy_cache   my_app; 
    proxy_cache_valid 15m; 
    proxy_cache_key  $uri$is_args$args; 
} 

Come si può vedere dalla sopra la configurazione, anche se abbiamo impostato esplicitamente chunked_transfer_encodingoff per tali percorsi come per i documenti nginx, avere proxy_bufferingon e avere uno spazio sufficiente proxy_bufferssize, la risposta è ancora suddivisa in blocchi.

Cosa ci manca qui?

--edit 1: versione info--

$ nginx -v 
nginx version: nginx/1.6.1 

$ node -v 
v0.10.30 

2 --edit: nginx gzip config--

# http://nginx.org/en/docs/http/ngx_http_gzip_module.html 
gzip on; 
gzip_buffers 32 4k; 
gzip_comp_level 1; 
gzip_min_length 1000; 
#gzip_http_version 1.0; 
gzip_types application/javascript text/css 
gzip_proxied any; 
gzip_vary on; 
+1

Dove stai dicendo nginx a gzip? Sta facendo uno streaming gzip, per il quale il chunked è l'unica opzione sensata. Invece dovresti avere le risorse statiche in formato raw e gzip e configurare nginx per servire le risorse gziped quando richiesto. In altre parole pre gzip invece di gzipping al volo. – generalhenry

+0

@generalhenry Ho aggiunto anche la configurazione 'gzip'. Hai ragione che i beni vengono zippati al volo. Ho anche visto il modulo 'gzip_static' che ti aiuta a fare quello che hai descritto. Quindi, suppongo che nel nostro caso, o dovremo ospitare le risorse raw + gzip su 'nginx', configurare' gzip_static' e poi farà la cosa giusta. Oppure, averli pre-compilati durante la nostra fase di creazione degli asset in 'Nodo', creare alcune intelligenze in cima a' express.static() 'per servire l'uno o l'altro in base alla richiesta corrente e disattivare' gzip' su ' nginx'. – kodeninja

+0

Sì gzip_proxied any; sembra essere il colpevole (disclaimer, non sono affatto un esperto di nginx, penso solo in termini di flussi) – generalhenry

risposta

1

Hai ragione, Vorrei esporre.

Le intestazioni sono la prima cosa che è necessario inviare. Tuttavia, dal momento che si utilizza la compressione di streaming, la dimensione finale è incerta. Conoscerai solo la dimensione della risorsa non compressa e anche l'invio di una lunghezza del contenuto troppo grande sarebbe errato.

Così, ci sono due opzioni:

  1. codifica di trasferimento chunked
  2. Completamente comprimere il bene prima di inviare tutti i dati, quindi la dimensione compressa è noto

Attualmente, si sta sperimentando il primo caso, e sembra che tu abbia davvero bisogno del secondo. Il modo più semplice per ottenere il secondo caso è di attivare gzip_static come @kodeninja ha detto nei commenti.

Problemi correlati