使用 nginx 终止 grpc 流量

Posted

技术标签:

【中文标题】使用 nginx 终止 grpc 流量【英文标题】:Terminate grpc traffic with nginx 【发布时间】:2018-09-20 07:12:05 【问题描述】:

This recent blogpost 表示 nginx 能够终止 http/2 grpc 流量。

从所有的插图和文字来看,它似乎根本无法终止grpc流量,只是代理、转发和路由流量。

原因是,我想通过 nginx 和 php 提供简单的服务。我知道 PHP 本身具有实现 http/2 和 grpc 的能力,但这有点“手动”,没有开箱即用的东西。如果我们可以使用 nginx 来终止,它可能会很容易工作。

从同一篇博文中我不明白的另一件事:

注意:NGINX 不支持在明文(非 TLS)端口上同时支持 HTTP/1 和 HTTP/2。它需要关于将使用哪个版本的协议的先验知识。如果您想通过明文处理这两个协议版本,请为每个版本创建一个侦听端口。

当两者都是明文时,实际使用的协议是预先知道的(因为它是明文),我们可以在同一个端口上监听两者。两个不同的端口只对我有意义,当其中一个协议是不是明文时。

谁能帮我弄清楚这两点?

【问题讨论】:

【参考方案1】:

对我来说,这意味着“终止”,即能够充当来自系统外部的用户的终点。就像您经常在边缘点(例如 Nginx)“终止”HTTPS 但随后将未加密的 HTTP 流量传递到下游服务器一样。

因此,您仍然需要一个单独的服务器来了解如何处理 gRPC,并且该服务器需要在端口上可用,以便 nginx 使用 grpc_pass 与其通信。

从PHP examples at the gRPC website看来,它似乎只使用 PHP 作为客户端 gRPC 应用程序而不是服务器端:

请注意,目前您只能在 PHP 中为 gRPC 创建客户端 服务 - 您可以在我们的其他网站中了解如何创建 gRPC 服务器 教程,例如Node.js。

因此,您需要服务器端 gRPC 服务器(例如 Node.js)来响应您的 gRPC 调用 - 这不能只是 nginx,尽管 nginx 可用于将 gRPC 调用路由到该 gRPC 服务器。在后端应用程序服务器前面有一个像 nginx 这样的网络服务器有多种原因,包括:SSL/TLS 卸载、静态内容处理、负载平衡......等等。

当两者都是明文时,实际使用的协议是已知的 前面(因为它是明文),我们可以在 同一个端口。

这并不像你想象的那么容易。解析消息以查看它们是一种协议还是另一种实际上非常复杂 - 特别是考虑到 HTTP/1 是文本的,HTTP/2 是二进制的,gRPC 仅使用 HTTP/2 作为传输层,甚至不使用底层的 HTTP 语义这个。

通常,HTTP 服务器可以通过三种方式知道它是否为 HTTP/2:

    最初使用明文 HTTP,然后将其升级到 HTTP/2。 在发送第一条 HTTP 消息之前,使用 ALPN(或更旧的 NPN)作为 TLS 设置的一部分协商使用加密的 HTTPS。 使用纯文本 HTTP,但假设它是 HTTP/2 连接(由于以前先验了解该端口上的服务),因此开始讨论 HTTP/2。

看起来 Nginx 确实允许将纯文本 HTTP/1.1 连接转换为 HTTP/2 的第一种升级方法。这意味着对于纯文本 HTTP,它只允许立即将连接用作 HTTP/2(“先验知识”)。有一个request to allow HTTP/1 and HTTP/2 to be used on the same port for different connections,但老实说,我可以理解为什么还没有完成,因为考虑到低优先级,考虑到目前 HTTP/2 的主要用例是浏览器(仅限 HTTPS)或对于像 gRPC 这样的服务,它可能应该知道它们是否是 HTTP/2。

另外,如上所述,gRPC 根本不是关于 HTTP 的——它只是使用 HTTP/2 的二进制框架层通过流控制的多路复用连接发送 gRPC 消息。这类似于 Websocket 使用 HTTP TCP 连接发送非 HTTP 消息的方式(尽管 Web 套接字通常使用 HTTP 语义来协商 Web 套接字连接)。

所以,正如我所说,在不使用 HTTPS 时不要让事情复杂化并尝试猜测协议对我来说实际上是有道理的 - 在大多数情况下应该知道它。

【讨论】:

感谢您的回复!我的理解不清楚,因为我假设“终止”(结束 http/2 并继续使用 http/1)和“明文”的含义略有不同。 所以如果我写一个理解 grpc 的 PHP 解析器,我可以把它用作服务器,对吗?这里有一个易于理解的协议表吗?

以上是关于使用 nginx 终止 grpc 流量的主要内容,如果未能解决你的问题,请参考以下文章

GRPC负载均衡

由于连接被强制终止,使用 ngrok 测试 gRPC 失败

使用 opsworks nginx 和 ELB 终止 SSL 时强制使用 HTTPS

nginx 1.13.10开始支持gRPC

GRPC+Nginx

使用 Nginx 的 gRPC 通信卡住