我遇到了一个问题,我无法让 nginx 与 gRPC 一起正常工作。我正在使用 .Net core 3.1 来为支持 REST 和 gRPC 的 API 提供服务。
我正在使用以下 docker 图像:
客户端在本地运行,因为我只是通过 nginx 连接到 docker 容器(端口 8080 和 443 映射到主机)
我已经在 docker 容器中构建了 API 映像,并且正在使用 docker compose 来启动所有内容。
在 gRPC 方面,我的 API 相当简单:
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<CartService>();
endpoints.MapControllers();
});
Run Code Online (Sandbox Code Playgroud)
我在我的 API 前面有 nginx 作为反向代理,下面是我的 nginx 配置。但是 rpc 调用不起作用。我无法通过客户端连接到 gRPC 服务,它返回 502 请求。我得到一个. 添加单独的 kestral 端点后(请参阅下面的 Edit1),我2020/06/29 18:33:30 [error] 27#27: *3 upstream sent too large http2 frame: 4740180 while reading response header from upstream, client: 172.20.0.1. *1 upstream prematurely closed connection while reading response header from upstream在查看 Nginx 日志时收到。
服务器甚至从未收到实际请求,因为当我查看 docker 日志时,服务器端没有记录任何内容。
几乎没有关于如何通过 .Net 上的 docker 支持 gRPC 的文档,因此不确定如何继续。需要配置/启用什么比我要让它工作更进一步?请注意,API 的 REST 部分工作正常,没有问题。不确定是否需要将 SSL 一直传送到上游服务器(即 API 级别的 SSL)。
我在 Nginx 上看到的 gRPC 文档与我在下面看到的完全一样。在 Nginx 中启用了 http_v2_module,我可以通过响应协议验证它是否适用于 API 的非 gRPC 部分。
http {
upstream api {
server apiserver:5001;
}
upstream function {
server funcserver:5002;
}
# redirect all http requests to https
server {
listen 80 default_server;
listen [::]:80 default_server;
return 301 https://$host$request_uri;
}
server {
server_name api.localhost;
listen 443 http2 ssl ipv6only=on;
ssl_certificate /etc/certs/api.crt;
ssl_certificate_key /etc/certs/api.key;
location /CartCheckoutService/ValidateCartCheckout {
grpc_pass grpc://api;
proxy_buffer_size 512k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 512k;
grpc_set_header Upgrade $http_upgrade;
grpc_set_header Connection "Upgrade";
grpc_set_header Connection keep-alive;
grpc_set_header Host $host:$server_port;
grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
grpc_set_header X-Forwarded-Proto $scheme;
}
location / {
proxy_pass http://api;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Connection keep-alive;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
server {
server_name func.localhost;
listen 443 ssl;
ssl_certificate /etc/certs/func.crt;
ssl_certificate_key /etc/certs/func.key;
location / {
proxy_pass http://function;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
gzip on;
gzip_vary on;
gzip_proxied no-cache no-store private expired auth;
gzip_types text/plain text/css application/json application/xml;
}
Run Code Online (Sandbox Code Playgroud)
编辑 1: 我还尝试为 REST/gRPC 启动单独的端点。从这件文件,当不安全的请求进来,它会自动认为是HTTP1请求。我手动将 kestrel 配置为具有 2 个单独的端点、两个端口 - 一个用于 http1+http2,另一个用于 http2 请求。
services.Configure<KestrelServerOptions>(y =>
{
y.ListenAnyIP(5010, o =>
{
o.Protocols = HttpProtocols.Http2;
//o.UseHttps("./certs/backend.pfx", "password1");
});
y.ListenAnyIP(5001, o =>
{
o.Protocols = HttpProtocols.Http1AndHttp2;
});
});
Run Code Online (Sandbox Code Playgroud)
在 Nginx 中,我也创建了一个单独的条目:
upstream api {
server apiserver:5001;
}
upstream grpcservice {
server apiserver:5010;
}
upstream function {
server funcserver:5002;
}
Run Code Online (Sandbox Code Playgroud)
这也不起作用。我什至通过使 htt2 端点只接受 ssl 连接而不接受骰子来尝试上游 SSL。
编辑2
我也试过如下:
他们都没有工作。
编辑 3:我终于能够完成这项工作:
location /CartCheckoutService/ValidateCartCheckout {
grpc_pass grpc://api;
}
Run Code Online (Sandbox Code Playgroud)
无论出于何种原因,nginx 唯一有效的配置是仅使用grpc_pass。它与代理通行证不同,不需要其他配置。我终于能够在不必执行上游 SSL 的情况下使其正常工作,而只需像我想的那样使用代理 - 在代理处终止 SSL。
我仍在寻找正式的解释,否则我会将我自己的解决方案标记为答案,因为我已成功对其进行了测试。
以下是有效的解决方案:
location /CartCheckoutService/ValidateCartCheckout {
grpc_pass grpc://api;
}
Run Code Online (Sandbox Code Playgroud)
使用 grpc 时,nginx 的唯一配置是仅使用grpc_pass。它与代理传递不同,并且不需要其他配置(即从请求中传递标头/协议/等)。我终于能够在不必执行上游 SSL 的情况下使其正常工作,而只需像我想的那样使用代理 - 在代理处终止 SSL。
| 归档时间: |
|
| 查看次数: |
4219 次 |
| 最近记录: |