2015-01-07 14 views
7

Chúng tôi có ứng dụng web Node/express đang phân phát nội dung tĩnh ngoài nội dung thông thường, qua express.static(). Có máy chủ nginx ở phía trước máy chủ hiện được định cấu hình thành gzip các yêu cầu nội dung tĩnh này, nếu số user agent phụ thuộc vào nó.Không thể tắt mã hóa chuyển chunked trong nginx với gzip cho các tài sản tĩnh được cung cấp từ Node backend

Tuy nhiên, mặc dù nginx được làm gzip như mong đợi, nó được thả Content-Length đánh đầu từ nguồn gốc, và thiết lập Transfer-Encoding: chunked để thay thế. Điều này phá vỡ bộ nhớ đệm trên CDN của chúng tôi.

Dưới đây là các câu trả lời cho một yêu cầu tài sản tĩnh điển hình (một file JS trong trường hợp này), từ backend nút, và từ nginx:

Yêu cầu:

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 

Tiêu đề phản hồi từ 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 

Headers Phản hồi từ 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 

cấu hình hiện tại nginx của chúng tôi cho các tài sản tĩnh location trông giống như dưới đây:

nginx cấu hình:

# 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; 
} 

Như có thể thấy từ ở trên cấu hình, mặc dù chúng tôi đã đặt rõ ràng chunked_transfer_encodingoff cho các đường dẫn như vậy theo tài liệu nginx, có proxy_bufferingon và có đủ lớn proxy_bufferssize, phản hồi vẫn đang được chunked.

Chúng ta thiếu gì ở đây?

--edit 1: phiên bản info--

$ nginx -v 
nginx version: nginx/1.6.1 

$ node -v 
v0.10.30 

--edit 2: 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

Bạn đang nói nginx với gzip ở đâu? Nó đang làm một gzip streaming, mà chunked là lựa chọn hợp lý duy nhất. Thay vào đó, bạn nên có các tài sản tĩnh ở dạng thô và gzipped và cấu hình nginx để phục vụ các nội dung gziped khi được yêu cầu. Nói cách khác trước gzip thay vì gzipping trên bay. – generalhenry

+0

@generalhenry Tôi cũng đã thêm cấu hình 'gzip'. Bạn nói đúng rằng các tài sản đang được nén trên bay. Tôi cũng thấy mô-đun 'gzip_static' giúp bạn làm những gì bạn đã mô tả. Vì vậy, tôi đoán trong trường hợp của chúng tôi, chúng tôi sẽ phải lưu trữ các tài nguyên thô gzipped trên 'nginx' chính nó, cấu hình' gzip_static' và sau đó nó sẽ làm điều đúng. Hoặc, có chúng được xây dựng sẵn trong giai đoạn xây dựng nội dung của chúng ta trong 'Node', xây dựng một số thông minh trên đầu trang' express.static() 'để phục vụ một hoặc khác dựa trên yêu cầu hiện tại và tắt' gzip' trên ' nginx'. – kodeninja

+0

Yeah gzip_proxied any; có vẻ là thủ phạm (tuyên bố từ chối trách nhiệm, tôi không phải là chuyên gia về nginx, tôi chỉ nghĩ về luồng) – generalhenry

Trả lời

1

Bạn là chính xác, hãy để tôi giải thích.

Tiêu đề là thứ đầu tiên cần được gửi. Tuy nhiên vì bạn đang sử dụng tính năng nén trực tuyến nên kích thước cuối cùng không chắc chắn. Bạn chỉ biết kích thước của nội dung chưa nén và gửi Nội dung quá dài cũng sẽ không chính xác.

Như vậy, có hai lựa chọn:

  1. mã hóa chuyển chunked
  2. Hoàn toàn Nén tài sản trước khi gửi bất kỳ dữ liệu, vì vậy kích thước nén được biết

Hiện tại, bạn đang gặp phải trường hợp đầu tiên, và có vẻ như bạn thực sự cần thứ hai. Cách dễ nhất để lấy trường hợp thứ hai là bật gzip_static như @kodeninja đã nói trong phần bình luận.

Các vấn đề liên quan