grpc / grpc-web

gRPC for Web Clients
https://grpc.io
Apache License 2.0
8.46k stars 762 forks source link

Use NGINX for grpc_pass get Bad gRPC response. HTTP status code: 500 or 502 #1307

Closed Kotnstantin closed 1 year ago

Kotnstantin commented 1 year ago

Problem statement:

Grpc client not connectin to grpc server when i use variable in nginx config.

When you have a configuration similar to this (example) it works, BUT until the one of services crashes, and if nginx restarts - in logs nginx not found service dev_webui in upstream and config not started.:

server {
    listen 443 http2:
    server _name opc.org.com;
    ssl....;
    location / {
        proxy_pass https://dev_webui;;
    }
    location /App.Room.Api.Contract.ApiService/UpdateOpcDaTags {
    grpc_pass grpcs://dev_webui;
    }

However, when I do the same with resolver and set grpc_pass it fails:

server {
    listen 443 http2:
    server _name opc.org.com;
    ssl....;
    location / {
        resolver 127.0.0.11 valid=30s;
        set $https_webui https://dev_webui;
        proxy_pass $https_webui;
    }  
    location /App.Room.Api.Contract.ApiService/UpdateOpcDaTags {
        resolver 127.0.0.11 valid=30s;
        set $grpc_webui grpcs://dev_webui;
        grpc_pass $grpc_webui;
    }

The error I'm getting on grpc-client is:

  [Microsoft.Extensions.Hosting.Internal.Host)
  [BackgroundServiceFaulted status   BackgroundServledGrpc.Co.RpcException
  (StatusCode="Unknown", Detail="Bad gRPC response. HTTP status code: 500")

Version nginx; nginx version: nginx/1.23.2

The goal is not to let nginx drop all available services when one of them drops.

To bypass the situation can configure nginx configuration through resolve and set $var directive for proxy_pass and grpc_pass, especially not prohibited by the documentation.

Help solve the problem why the server cannot see the grpc client variable when it is installed

Kotnstantin commented 1 year ago

After a long review of the materials and tests, the error was discovered.

If we are using variables in the configuration, grpc_pass should have a port on which this grpc can be listened, in this example https and grpcs will use port 443.

So the working configuration for me is:

`server {
    listen 443 http2:
    server _name opc.org.com;
    ssl....;
    location / {
        resolver 127.0.0.11 valid=30s;
        set $https_webui https://dev_webui;
        proxy_pass $https_webui;
    }  
    location /App.Room.Api.Contract.ApiService/UpdateOpcDaTags {
        resolver 127.0.0.11 valid=30s;
        set $grpc_webui grpcs://dev_webui:443;
        grpc_pass $grpc_webui;
    }`

Interestingly, for proxy_pass port is not necessary to specify, I think due to the indication of https://

With this configuration, any stack that nginx maintains can be wiped out of the available stacks, and nginx will not send host not found in upstream message when restarted