簡體   English   中英

nginx 代理后面帶有 node.js 的 HTTP2

[英]HTTP2 with node.js behind nginx proxy

我有一個在 nginx 代理后面運行的 node.js 服務器。 node.js 在端口 3000 上運行 HTTP 1.1(無 SSL)服務器。兩者都在同一台服務器上運行。

我最近將 nginx 設置為使用帶有 SSL (h2) 的 HTTP2。 似乎 HTTP2 確實已啟用並且可以正常工作。

但是,我想知道代理連接 (nginx <--> node.js) 使用 HTTP 1.1 是否會影響性能。 也就是說,我是否因為我的內部連接是 HTTP 1.1 而錯過了 HTTP2 在速度方面的優勢?

一般來說,HTTP/2 最大的直接好處是通過多路復用為瀏覽器連接提供的速度提升,而瀏覽器連接通常受到高延遲(即緩慢的往返速度)的阻礙。 這些還減少了對多個連接的需求(和費用),這是一種嘗試在 HTTP/1.1 中實現類似性能優勢的解決方法。

對於內部連接(例如充當反向代理的網絡服務器和后端應用程序服務器之間),延遲通常非常非常低,因此 HTTP/2 的速度優勢可以忽略不計。 此外,每個應用服務器通常已經是一個單獨的連接,因此這里也沒有任何好處。

因此,您只需在邊緣支持 HTTP/2,即可獲得大部分性能優勢。 這是一個相當常見的設置 - 類似於 HTTPS 通常在反向代理/負載平衡器上終止而不是一直通過的方式。

然而,一直支持 HTTP/2 有潛在的好處。 例如,它可以允許服務器從應用程序一路推送。 由於 HTTP/2 和標頭壓縮的二進制性質,最后一跳的數據包大小減小也有潛在好處。 但是,與延遲一樣,帶寬對於內部連接而言通常不是問題,因此其重要性值得商榷。 最后,有些人認為,反向代理將 HTTP/2 連接到 HTTP/2 連接的工作量少於連接到 HTTP/1.1 連接的工作量,因為不需要將一種協議轉換為另一種協議,盡管我對此表示懷疑值得注意,因為它們是單獨的連接(除非它只是作為 TCP 直通代理)。 所以,對我來說,端到端 HTTP/2 的主要原因是允許端到端服務器推送,但即使這樣也可能更好地處理 HTTP 鏈接頭和 103-Early 提示,因為管理跨多個連接的推送很復雜.

目前,雖然服務器仍在添加支持並且服務器推送使用率很低(並且仍在試驗以定義最佳實踐),但我建議僅在端點使用 HTTP/2。 在撰寫本文時,Nginx 也不支持 ProxyPass 連接的 HTTP/2(盡管 Apache 支持),並且沒有計划添加此功能,並且他們提出了一個有趣的觀點,即單個 HTTP/2 連接是否可能會導致緩慢(強調我的):

是否計划在不久的將來支持 HTTP/2 代理?

簡短的回答:

不,沒有計划。

長答案:

幾乎沒有實現它的意義,因為 HTTP/2 的主要好處是它允許在單個連接中多路復用多個請求,因此 [幾乎] 消除了對同時請求數量的限制——並且在與之交談時沒有這樣的限制你自己的后端。 此外,當使用 HTTP/2 到后端時,情況甚至可能變得更糟,因為使用的是單個 TCP 連接而不是多個 TCP 連接

另一方面,在上游模塊的單個連接中實現 HTTP/2 協議和請求多路復用將需要對上游模塊進行重大更改。

由於上述原因,至少在可預見的未來,沒有計划在上游模塊中實現 HTTP/2 支持。 如果您仍然認為需要通過 HTTP/2 與后端​​通信 - 請隨時提供補丁。

最后,還應該注意的是,雖然瀏覽器需要 HTTP/2 (h2) 的 HTTPS,但大多數服務器不需要,因此可以支持 HTTP (h2c) 上的最后一跳。 因此,如果 Node 部分不存在端到端加密(通常不存在),則不需要端到端加密。 但是,根據后端服務器相對於前端服務器的位置,如果流量將通過不安全的網絡(例如 CDN 到 Internet 上的源服務器)傳輸,即使為此連接使用 HTTPS 也可能是應該考慮的事情。

NGINX 現在支持proxy_pass HTTP2/Push 並且它很棒......

在這里,我也從我的靜態子域中推送 favicon.ico、minified.css、minified.js、register.svg、purchase_litecoin.svg。 我花了一些時間才意識到我可以從子域推送。

location / {
            http2_push_preload              on;
            add_header                      Link "<//static.yourdomain.io/css/minified.css>; as=style; rel=preload";
            add_header                      Link "<//static.yourdomain.io/js/minified.js>; as=script; rel=preload";
            add_header                      Link "<//static.yourdomain.io/favicon.ico>; as=image; rel=preload";
            add_header                      Link "<//static.yourdomain.io/images/register.svg>; as=image; rel=preload";
            add_header                      Link "<//static.yourdomain.io/images/purchase_litecoin.svg>; as=image; rel=preload";
            proxy_hide_header               X-Frame-Options;
            proxy_http_version              1.1;
            proxy_redirect                  off;
            proxy_set_header                Upgrade $http_upgrade;
            proxy_set_header                Connection "upgrade";
            proxy_set_header                X-Real-IP $remote_addr;
            proxy_set_header                Host $http_host;
            proxy_set_header                X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header                X-Forwarded-Proto $scheme;
            proxy_pass                      http://app_service;
        }

萬一有人在不方便使您的服務兼容 HTTP2 時為此尋找解決方案。 以下是可用於將 HTTP1 服務轉換為 HTTP2 服務的基本 NGINX 配置。

server {
  listen [::]:443 ssl http2;
  listen 443 ssl http2;

  server_name localhost;
  ssl on;
  ssl_certificate /Users/xxx/ssl/myssl.crt;
  ssl_certificate_key /Users/xxx/ssl/myssl.key;

  location / {
    proxy_pass http://localhost:3001;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
  }
}

NGINX 不支持 HTTP/2 作為客戶端。 由於它們在同一台服務器上運行並且沒有延遲或帶寬有限,我認為這兩種方式都不會產生巨大的不同。 我會確保你在 nginx 和 node.js 之間使用 keepalives。

https://www.nginx.com/blog/tuning-nginx/#keepalive

您通常不會損失性能,因為 nginx 通過向您的節點后端創建多個並發請求來匹配瀏覽器通過 HTTP/2 執行的多路復用請求。 (HTTP/2 的主要性能改進之一是允許瀏覽器在同一連接上同時執行多個請求,而在 HTTP 1.1 中,每個連接只能同時請求一個。瀏覽器也限制了連接數。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM