debian9 编译nginx 1.14.0 配置gRPC

Nginx 在 1.13.10 中,新增了对gRPC的原生支持,Nginx 1.14.0 主线版已经发布。

安装 Nginx
Nginx版本要求:1.13.10+。gRPC必须使用 HTTP/2 传输数据,支持明文和TLS加密数据,支持流数据的交互。这是为了充分利用 HTTP/2 连接的多路复用和流式特性。所以在安装部署nginx时需要安装http/2。使用源码安装,编译时需要加入http_ssl和http_v2模块:

1
./configure --with-http_ssl_module --with-http_v2_module
安装软件包:
1
2
3
4
5
apt update
apt install gcc make
apt install libpcre3 libpcre3-dev //【正则表达式库】 官网http://www.pcre.org/
apt install openssl libssl-dev //【openssl库】 官网https://www.openssl.org/
apt install zlib1g-dev
创建需要使用的目录

创建目录source和release,分别用来放源码和编译后的文件

1
2
mkdir /source/
mkdir /release/

安装nginx
1
2
3
4
5
6
7
8

# cd /source/

# wget http://nginx.org/download/nginx-1.14.0.tar.gz
# tar -zxf nginx-1.14.0.tar.gz
# cd nginx-1.14.0
# ./configure --prefix=/release/nginx --with-http_ssl_module --with-http_v2_module
# make && make install
nginx 命令
1
2
3
4
# ln -s /web/nginx/sbin/nginx /usr/local/bin //快捷方式
# /release/nginx/sbin/nginx //启动nginx
# /release/nginx/sbin/nginx -s reload //重启nginx
# /release/nginx/sbin/nginx -s stop //关闭nginx

以明文的方式发布gRPC服务。

nginx是使用http服务器监听gRPC的请求。示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
http {
server {
listen 80 http2;

access_log logs/access.log main;

location / {
# The 'grpc://' prefix is optional; unencrypted gRPC is the default
grpc_pass grpc://localhost:50051;
}
}
}

在 Nginx 中配置 gRPC 的代理

指令grpc_pass用来指定代理的gRPC服务器地址,前缀协议有两种:

grpc://:与gRPC服务器端交互是以明文的方式
grpcs://:与gRPC服务器端交互式以TLS加密方式
gRPC服务器地址的前缀“grpc://”是可以忽略,默认就是明文交互方式。

此示例里nginx以明文的方式在80端口发布gRPC,其中代理的gRPC在后端也是以明文的方式交互。

注意:Nginx是不支持在明文的端口上同时支持http1和http2的(想一想为什么?)。如果要支持这两种的http协议,需要设置为不同的端口。

以 TLS 加密方式发布 gRPC 服务
在生成环境建议使用Nginx是以加密的方式发布gRPC。这种情景需要在Nginx添加一个加密层。

在开发/测试环境可以使用自签名证书,关于自签名证书本文不做介绍。配置示例如下:

1
2
3
4
5
6
7
8
9
10
server {
listen 1443 ssl http2;

ssl_certificate ssl/cert.pem;
ssl_certificate_key ssl/key.pem;

location / {
grpc_pass grpc://localhost:50051;
}
}

示例里在nginx层给gRPC服务添加了ssl证书,而内部代理到gRPC服务器仍然是使用明文的交互方式,也就是在Nginx层,做到了SSL offloading。

gRPC客户端也是需要TLS加密。如果是使用自签名证书等未经信任的证书,客户端都需要禁用证书检查。在部署到生产环境时,需要将自签名证书换成由可信任证书机构发布的证书,客户端也需要配置成信任该证书。

代理加密的gRPC

如果Nginx内部代理的gRPC也需要以加密的方式交互,这种情况就需要把明文代理协议grpc://替换为grpcs://。这首先要gRPC服务器是以加密的方式发布服务的。Nginx层修改如下:

1
grpc_pass grpcs://localhost:50051;

nginx路由gRPC请求

如果后端有多个gRPC服务端,其中每个服务端都是提供不同的gRPC服务。这种情况可以使用一个nginx接收客户端请求,然后根据不同的路径分发路由到指定的gRPC服务器。使用location区分:

1
2
3
4
5
6
7
8
9
10
11
12
location /helloworld.Greeter {
grpc_pass grpc://192.168.20.11:50051;
}

location /helloworld.Dispatcher {
grpc_pass grpc://192.168.20.21:50052;
}

location / {
root html;
index index.html index.htm;
}

对gRPC请求做负载均衡

在后端有多个gRPC服务器,它们都是同一个gRPC服务,这种情况可以结合nginx的upstream可以对gRPC的请求做负载均衡。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
upstream grpcservers {
server 192.168.20.21:50051;
server 192.168.20.22:50052;
}

server {
listen 1443 ssl http2;

ssl_certificate ssl/certificate.pem;
ssl_certificate_key ssl/key.pem;

location /helloworld.Greeter {
grpc_pass grpc://grpcservers;
error_page 502 = /error502grpc;
}

location = /error502grpc {
internal;
default_type application/grpc;
add_header grpc-status 14;
add_header grpc-message "unavailable";
return 204;
}
}

其中upstream指定定义了统一gRPC服务的服务器组。在grpc_pass指定的gRPC服务器地址使用upstream定义的服务器组。

参考:

如何在 Nginx 中配置 gRPC 的代理

Debian9 从零编译配置Nginx