HTTP2与nginx代理背后的node.js

ac1kyiln  于 2023-05-22  发布在  Nginx
关注(0)|答案(5)|浏览(226)

我有一个node.js服务器在nginx代理后面运行。node.js在端口3000上运行HTTP 1.1(无SSL)服务器。两者都运行在同一台服务器上。
我最近设置了nginx使用HTTP2和SSL(h2)。看来HTTP2确实是启用和工作。
但是,我想知道代理连接(nginx <-->node.js)使用HTTP 1.1是否会影响性能。也就是说,我是否因为我的内部连接是HTTP 1.1而错过了HTTP2在速度方面的好处?

vojdkbi0

vojdkbi01#

一般来说,HTTP/2最大的直接好处是multiplexing为浏览器连接提供的速度提高,而浏览器连接通常会受到高延迟(即慢往返速度)。这些也减少了多个连接的需求(和费用),这是一种尝试在HTTP/1.1中实现类似性能优势的工作。
对于内部连接(例如在充当反向代理的web服务器和后端应用服务器之间),延迟通常非常非常低,因此HTTP/2的速度优势可以忽略不计。此外,每个应用服务器通常已经是一个单独的连接,因此这里同样没有收益。
因此,您将从仅在边缘支持HTTP/2中获得的性能优势。这是一种相当常见的设置--类似于HTTPS通常在反向代理/负载均衡器上终止而不是完全终止的方式。
然而,支持HTTP/2的所有方式都有潜在的好处。例如,它可以允许服务器从应用程序一路推送。由于HTTP/2的二进制性质和报头压缩,最后一跳的数据包大小减小也有潜在的好处。虽然,像延迟一样,带宽对于内部连接来说通常不是一个问题,所以这一点的重要性是有争议的。最后,有些人认为反向代理在连接HTTP/2连接到HTTP/2连接时所做的工作比连接到HTTP/1.1连接时少,因为不需要将一个协议转换为另一个协议,尽管我怀疑这是否值得注意,因为它们是独立的连接(除非它只是作为TCP通过代理)。所以,对我来说,端到端HTTP/2的主要原因是允许端到端服务器推送,但是even that is probably better handled with HTTP Link Headers and 103-Early Hints due to the complications in managing push across multiple connections和我不知道任何HTTP代理服务器会支持这一点(很少有足够的后端支持HTTP/2,更不用说像这样链接HTTP/2连接),所以你需要一个第4层负载均衡器转发TCP打包器,而不是链接HTTP请求-这会带来其他复杂性。
目前,虽然服务器仍在增加支持,服务器推送的使用率很低(仍在进行实验以定义最佳实践),但我建议只在端点使用HTTP/2。在撰写本文时,Nginx也不支持HTTP/2用于ProxyPass连接(尽管Apache支持),并且具有no plans to add this,并且他们提出了一个有趣的观点,即单个HTTP/2连接是否会引入缓慢(强调我的):
HTTP/2代理支持计划在不久的将来?
简短回答:
不,没有计划。
长回答:
实现它几乎没有意义,因为HTTP/2的主要好处是它允许在单个连接中多路复用许多请求,因此[几乎]消除了对相同请求数量的限制-并且在与您自己的后端对话时没有这样的限制。此外,当使用HTTP/2到后端时,情况甚至可能变得更糟,因为使用单个TCP连接而不是多个连接
另一方面,在上游模块中的单个连接内实现HTTP/2协议和请求多路复用将需要对上游模块进行重大更改。
由于上述原因,至少在可预见的将来,没有计划在上游模块中实现HTTP/2支持。如果您仍然认为通过HTTP/2与后端通信是必要的-请随时提供补丁。
最后,还应该注意的是,虽然浏览器需要HTTP/2(h2)的HTTPS,但大多数服务器不需要,因此可以支持HTTP(h2 c)的最后一跳。因此,如果Node部分不存在端到端加密(通常不存在),则不需要端到端加密。尽管如此,根据后端服务器相对于前端服务器的位置,如果流量将通过不安全的网络(例如:CDN到互联网上的源服务器)。

编辑2021年8月

HTTP/1.1是基于文本的,而不是基于binary的,这使得它容易受到各种请求走私攻击。在Defcon 2021 PortSwigger demonstrated a number of real-life attacks中,主要涉及将前端HTTP/2请求降级为后端HTTP/1.1请求时的问题。这些可能大多可以通过一直使用HTTP/2来避免,但是考虑到当前支持前端服务器和CDN向后端使用HTTP/2,以及后端支持HTTP/2,似乎需要很长时间才能实现这一点,并且前端HTTP/2服务器确保这些攻击不会被利用似乎是更现实的解决方案。

mrfwxfqh

mrfwxfqh2#

NGINX现在支持proxy_pass的HTTP 2/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;
        }
oprakyz7

oprakyz73#

如果有人正在寻找一个解决方案时,这是不方便,使您的服务HTTP2兼容。下面是基本的NGINX配置,您可以使用它将HTTP1服务转换为HTTP2服务。

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

o7jaxewo4#

NGINX不支持HTTP/2作为客户端。由于它们运行在同一台服务器上,没有延迟或有限的带宽,我不认为这会有很大的不同。我会确保你在nginx和node.js之间使用keepalives。
https://www.nginx.com/blog/tuning-nginx/#keepalive

r8xiu3jd

r8xiu3jd5#

一般来说,你不会失去性能,因为nginx通过创建多个并发请求到你的节点后端来匹配浏览器通过HTTP/2进行的请求多路复用。(HTTP/2的主要性能改进之一是允许浏览器在同一个连接上同时进行多个请求,而在HTTP 1.1中,每个连接只能同时进行一个请求。浏览器也限制了连接的数量。)

相关问题