4

我正在尝试更新我们的在线商店以使用具有服务器推送功能的 HTTP/2,但我找不到像 Nginx(用于代理和其他一些东西)这样的具有上游 HTTP/2 的网络服务器的解决方案。我们目前正在使用 Node.js 和 node HTTP 模块,但想切换到 node spdy 模块。spdy 模块支持 HTTP/2 和服务器推送。我曾尝试将 H2O 作为 Nginx 的替代品,但它也不支持上游的 HTTP/2。

我现在有点迷路,需要帮助。

4

3 回答 3

2

Nginx刚刚添加了对 HTTP/2 Push 的支持,所以除非你正在修改最新的主线版本,否则你将无法做到这一点。也因为它太新了,它仍然存在一些问题。Nginx 不支持通过后端连接的 http2(并且已经声明他们不会支持这个)。因此,您不能像您建议的那样直接从下游系统一直向上推送。

无论如何,这是否是最好的推动方式存在一些问题。即使客户端不支持推送,下游系统也可以推送到上游代理服务器——这是一种浪费的推送。

所以更好的方法是从代理推送,让下游系统告诉上游系统(通过链接头)进行推送。这在降低复杂性方面有几个优点,允许下游系统推送它可能无法控制的资产(例如,样式表、JavaScript、图像等静态资产),已推送资产(缓存摘要)的中央存储,也不是要求始终支持 HTTP/2(链接标头可以通过 HTTP/1.1 像 HTTP/2 一样容易地发送)。

通过链接头从上游代理推送的主要缺点是,当从响应中读取链接头时,您必须等待请求的资源准备好。如果请求资源需要一些时间来生成,那么在处理它的同时开始推送其他资源可能更有益。这可以通过新的103 Early Hints HTTP 状态代码解决,您可以在稍后发送主要的 200 状态代码之前提前回复。该早期消息可以具有上游代理可以读取并用于推送资源的链接标头。我不确定 Nginx 实现是否会支持这一点。

顺便说一句,Apache 已经支持 Push 有一段时间了,并且有一个更成熟的实现。它通过直接的 Apache 配置或链接头来支持它(包括通过默认配置为不发送的 103 响应,以防出现兼容性问题)。它甚至支持通过 HTTP/2 代理到后端,但由于上述原因不支持直接推送后端连接。其他一些不太知名的服务器(例如H2O)也比 Nginx 更好地支持 HTTP/2。

最后,如果使用 CDN,那么它们可能支持 HTTP/2 推送(通常通过链接头),而您无需升级任何后端基础设施。事实上,Cloudflare 是一个基于 Nginx 的 CDN,它使用HTTP/2 Push 已经有一段时间了,我实际上是两个 Cloudflare 工程师将他们的实现反向移植到了基本的 Nginx 代码

于 2018-02-14T12:31:21.807 回答
1

在 NGINX 1.13.9(今天刚刚推送到主线)之后,您可以通过使用ngx_http_v2_module.

如果您对最近添加的内容感兴趣,这是添加大部分功能的提交:hg.nginx.org: HTTP/2: server push

它的使用相对简单:将http2_push_preload指令添加到代理节点的服务器,然后从节点使用Link标头(如 W3 规范中所述 - https://www.w3.org/TR/preload/#server- push-http-2),然后 NGINX 将完成发送指示服务器推送的 h2 帧的工作。

例如,假设您有一个/提供常规服务index.html但也推image.svg送到客户端的端点。

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

然后在 NodeJS 应用程序中,您将像往常一样提供服务,但在响应中/添加一个额外的标头:Link

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

ps.:是的,你会保留那些尖括号;我并不是说你应该更换它们。

顺便说一句,我刚刚给出的示例(带有一些调试提示)已完整地写在这里:https ://ops.tips/blog/nginx-http2-server-push/ 。

于 2018-02-14T01:19:14.817 回答
0

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

于 2019-07-05T06:39:50.597 回答