简体   繁体   English

使用Push in Nodejs,Nodejs http2落后于(nginx或其他Webserver)

[英]Nodejs http2 behind (nginx or otherwise Webserver) with Push in Nodejs

I am trying to update our online shop to use HTTP/2 with Server Push capabilities but I can't find a solution for a webserver like Nginx(for proxying and some other stuff) with upstream HTTP/2. 我正在尝试更新我们的在线商店以使用具有服务器推送功能的HTTP / 2,但我找不到像Nginx这样的网络服务器(用于代理和其他一些东西)与上游HTTP / 2的解决方案。 We are using Node.js with the node HTTP module at the moment, but would like to switch to the node spdy module. 我们目前正在将Node.js与节点HTTP模块一起使用,但是想切换到节点spdy模块。 The spdy module supports HTTP/2 with Server Push. spdy模块支持带服务器推送的HTTP / 2。 I have tried H2O as an alternative to Nginx, but it doesn't support HTTP/2 upstream either. 我已经尝试过H2O作为Nginx的替代品,但它也不支持HTTP / 2上游。

I am kind of lost at the moment and need help. 我现在有点失落,需要帮助。

Nginx has only just added support for HTTP/2 Push so unless you are rubbing the latest mainline version you will not be able to do this. Nginx 刚刚添加了对HTTP / 2 Push的支持,所以除非你正在摩擦最新的主线版本,否则你将无法做到这一点。 Also because it is so new there are still some issues with it . 还因为它是如此新颖,它仍然存在一些问题 Nginx do not support http2 over backend connections (and have stated they won't support this ). Nginx不支持后端连接上的http2(并声明他们不支持这个 )。 So you cannot directly push from a downstream system all the way up like you suggest. 所以你不能像你建议的那样直接从下游系统推出。

There is some question as to whether that is the best way to push anyway. 无论如何,这是否是推动的最佳方式还存在一些问题。 A downstream system may push to the upstream proxy server even if the client does not support push for example - which is a wasted push. 即使客户端不支持推送,下游系统也可以推送到上游代理服务器 - 这是浪费的推送。

So the better way is to push from the proxy and have the downstream system tell the upstream system (via link headers) to do that push. 因此,更好的方法是从代理推送并让下游系统告诉上游系统(通过链接头)执行该推送。 This has several advantages in reducing complexity, allowing the downstream system to push assets it may not control (eg static assets like stylesheets, JavaScript, images... etc.), a central store of already pushed assets (cache digests) and also not requiring HTTP/2 to be supported all the way through (link headers can be sent over HTTP/1.1 as easily as HTTP/2). 这在降低复杂性方面有几个优点,允许下游系统推送它可能无法控制的资产(例如静态资产,如样式表,JavaScript,图像......等),已推送资产的中央存储(缓存摘要),也不要求HTTP / 2一直受到支持(链接头可以像HTTP / 2一样通过HTTP / 1.1发送)。

The main downside to pushing from the upstream proxy via link headers is that you have to wait for the requested resource to be ready as the link headers are read from the response. 通过链接头从上游代理推送的主要缺点是,您必须等待所请求的资源准备就绪,因为从响应中读取了链接头。 If the request resource takes some time to generate then it may be more beneficial to start pushing other resources while it's being processed. 如果请求资源需要一些时间来生成,那么在处理其他资源时开始推送可能更有利。 This is solved by a new 103 Early Hints HTTP Status code where you can reply back earlier before sending the main 200-status code later. 这是通过新的103 Early Hints HTTP状态代码解决的 ,您可以在稍后发送主200状态代码之前回复。 This early message can have link headers which can be read by the upstream proxy and be used to push the resource. 此早期消息可以具有链接头,其可以由上游代理读取并用于推送资源。 I am not sure if Nginx implementation will support this. 我不确定Nginx的实现是否会支持这一点。

Incidentally Apache has supported Push for a while now and has a much more mature implementation. 顺便说一下,Apache已经支持Push一段时间了,并且有一个更加成熟的实现。 It supports it via direct Apache config or via link headers (including via 103 responses which by default are configured not to be sent on in case on compatibility issues). 它通过直接Apache配置或链接头支持它(包括通过103响应,默认情况下配置为在兼容性问题时不发送)。 It even supports proxying to backends via HTTP/2 though does not support direct push over back end connections for reasons described above. 它甚至支持通过HTTP / 2代理后端,但由于上述原因,不支持直接推送后端连接 Some other less well known servers (eg H2O ) also support HTTP/2 better than Nginx. 其他一些不太知名的服务器(例如H2O )也比Nginx更好地支持HTTP / 2。

Finally if using a CDN then they may support HTTP/2 Push (often via link headers) without you having to upgrade any of your backend infrastructure. 最后,如果使用CDN,那么他们可能支持HTTP / 2推送(通常通过链接头),而无需升级任何后端基础设施。 In fact Cloudflare is an Nginx based CDN which has had HTTP/2 Push for a while and I fact it's two Cloudflare engineers which have back ported their implementation to the base Nginx code . 事实上,Cloudflare是一个基于Nginx的CDN,它有一段时间的HTTP / 2推送,事实上它是两个Cloudflare工程师,他们已经将他们的实现移植到基本的Nginx代码

After NGINX 1.13.9 (just pushed to mainline today) you're able to have HTTP/2 server push out of the box by compiling it with the ngx_http_v2_module . 在NGINX 1.13.9(今天刚推到主线)之后,您可以通过使用ngx_http_v2_module编译来启用HTTP / 2服务器。

If you're interested in the recent addition, this is the commit that added most of the functionality: hg.nginx.org: HTTP/2: server push . 如果您对最近添加的内容感兴趣,那么这是添加了大部分功能的提交: hg.nginx.org:HTTP / 2:服务器推送

Its use is relatively straightforward: add the http2_push_preload directive to the server that is proxying Node and then from node make use of the Link header (as described in the W3 spec - https://www.w3.org/TR/preload/#server-push-http-2 ) and then NGINX will do the job of sending the h2 frame that indicates a server push. 它的使用相对简单:将http2_push_preload指令添加到代理Node的服务器,然后从节点添加Link头(如W3规范中所述 - https://www.w3.org/TR/preload/# server-push-http-2 )然后NGINX将完成发送指示服务器推送的h2帧的工作。

For instance, assume that you have a / endpoint that serves a regular index.html but also pushes image.svg to the client. 例如,假设您有一个服务于常规index.html/ endpoint,但也将image.svgimage.svg客户端。

In NGINX you could configure an upstream server and then in the server configuration enable http2_push_preload on the server configuration: 在NGINX中,您可以配置上游服务器,然后在服务器配置中启用服务器配置上的http2_push_preload

# Add an upstream server to proxy requests to.
upstream sample-http1 {
  server localhost:8080;
}


server {
  # Listen on port 8443 with http2 support on.
  listen                  8443 http2;


  # Enable TLS such that we can have proper HTTP2
  # support using browsers.
  ssl on;
  ssl_certificate         certs/cert_example.com.pem;
  ssl_certificate_key     certs/key_example.com.pem;


  # Enable support for using `Link` headers to indicate
  # origin server push.
  http2_push_preload on;


  # Act as a reverse proxy for requests going to /proxy/*.
  #
  # Because we don't want to rewrite our endpoints in the
  # Node app, rewrite the path such that `/proxy/lol` ends up
  # as `/lol`.
  location / {
    proxy_pass      http://sample-http1;
  }
}

Then in the NodeJS app, you'd serve / as you'd normally do but add an extra Link header to the response: 然后在应用程序的NodeJS,你会成为/因为你通常做,但额外添加Link标题的回应:

response.setHeader('Link', '</image.svg>; rel=preload; as=image');

ps.: yeah, you'd keep those angle brackets; ps:是的,你要保留那些尖括号; I do not mean that you should replace them. 我并不是说你应该更换它们。

By the way, the example I just gave (with some debugging tips) is written up in complete here: https://ops.tips/blog/nginx-http2-server-push/ . 顺便说一下,我刚刚给出的示例(带有一些调试技巧)在这里写完: https//ops.tips/blog/nginx-http2-server-push/

您可以从源代码编译/重新编译nginx,并包含--with-http_v2_module配置参数以启用HTTP2推送功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM