将 NGINX 代理连接到 Envoy for gRPC-Web

发布于 2025-01-13 05:34:18 字数 3855 浏览 4 评论 0原文

我目前正在开发一个带有 gRPC 后端的 Web 应用程序。为此,我在 web 应用程序和后端服务之间使用 gRPC-Web 和 Envoy 代理。一切都很顺利,但现在我想将其部署到 digitalocean 服务器,并将 NGINX 设置为反向代理并为我的 index.html 文件提供服务。以下基本上是我的架构以及各个服务的端口。 Envoy 代理和 gRPC 后端在 Docker 容器中运行: 系统设计

我的 nginx.conf 现在看起来像这样:

server {
    listen 80;
    listen [::]:80;

    root /var/www/;

    index index.html index.htm;

    server_name myDomain.com

    location / {
        try_files $uri $uri /index.html?$args;
    }

    location /api {
        proxy_http_version 1.1;
        proxy_pass http://localhost:8000;
        proxy_set_header Connection "";
    }
}

我现在也会收到错误

grpc-message: "unknown service api/proto.Service"
grpc-status: "12"

即使该方法已实现并且在本地运行良好, 。 非常感谢任何帮助:)

编辑: 经过一些调试后,我认为问题是通过 Envoy 和 Nginx 从服务返回答案。 例如,当我在 Envoy 代理正在运行但后端服务未运行时发送请求时,我收到正确的错误 503(服务不可用)。 一旦后端 gRPC 服务再次运行,我就会收到 unkown service api/proto.Service 错误。

根据要求,我的 docker-compose.yaml 文件:

version: "3.9"
services:
  postgres:
    container_name: postgres
    hostname: postgres
    volumes:
      - ./management/postgres/postgres_data:/var/lib/postgresql/data
    build: ./management/postgres/
    ports: 
      - "5432:5432"
    environment:
      - POSTGRES_USER=$DB_USER
      - POSTGRES_PASSWORD=$DB_PWD
      - POSTGRES_DB=$DB_NAME

  backend:
    container_name: backend
    ports: 
      - "50051:50051"
    depends_on:
      - postgres
    build: ./service
    environment:
      - POSTGRES_PASSWORD=$DB_PWD

  envoy:
    build: ./management/proxies
    ports:
      - "8000:8000"

我的 envoy.yaml 代理:

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 0.0.0.0, port_value: 9901 }

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8000 }
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route:
                  cluster: grpc_server 
                  timeout: 0s
                  max_stream_duration:
                    grpc_timeout_header_max: 0s
              cors:
                allow_origin_string_match:
                - prefix: "*"
                allow_methods: GET, PUT, DELETE, POST, OPTIONS
                allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
                max_age: "1728000"
                expose_headers: custom-header-1,grpc-status,grpc-message
          http_filters:
          - name: envoy.filters.http.grpc_web
          - name: envoy.filters.http.cors
          - name: envoy.filters.http.router
  clusters:
  - name: grpc_server
    connect_timeout: 0.25s
    type: logical_dns
    http2_protocol_options: {}
    lb_policy: round_robin
    load_assignment:
      cluster_name: cluster_0
      endpoints:
        - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: backend
                    port_value: 50051

I am currently developing a webapp with a gRPC backend. For this I am using gRPC-Web and the Envoy proxy between the webapp and the backend service. It is all going fine but now I wanted to deploy it to a digitalocean server and was setting up NGINX as a reverse proxy and to serve my index.html file. The following is basically my architecture with the ports of the individual services. The Envoy proxy and the gRPC backend are running in Docker containers:
System Design

My nginx.conf now looks like this:

server {
    listen 80;
    listen [::]:80;

    root /var/www/;

    index index.html index.htm;

    server_name myDomain.com

    location / {
        try_files $uri $uri /index.html?$args;
    }

    location /api {
        proxy_http_version 1.1;
        proxy_pass http://localhost:8000;
        proxy_set_header Connection "";
    }
}

Now I am getting the error

grpc-message: "unknown service api/proto.Service"
grpc-status: "12"

even if the method is implemented and it is running great locally.
Any help is highly appreciated :)

EDIT:
After some debugging, I am thinking that returning the answer from the service through Envoy and Nginx is the issue.
For example, when I send the request while the Envoy proxy is running BUT the backend service is not running, I am getting the correct error 503 (Service Unavailable).
As soon as the backend gRPC service is running again, I am reciving the unkown service api/proto.Service error.

As requested, my docker-compose.yaml file:

version: "3.9"
services:
  postgres:
    container_name: postgres
    hostname: postgres
    volumes:
      - ./management/postgres/postgres_data:/var/lib/postgresql/data
    build: ./management/postgres/
    ports: 
      - "5432:5432"
    environment:
      - POSTGRES_USER=$DB_USER
      - POSTGRES_PASSWORD=$DB_PWD
      - POSTGRES_DB=$DB_NAME

  backend:
    container_name: backend
    ports: 
      - "50051:50051"
    depends_on:
      - postgres
    build: ./service
    environment:
      - POSTGRES_PASSWORD=$DB_PWD

  envoy:
    build: ./management/proxies
    ports:
      - "8000:8000"

My envoy.yaml proxy:

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 0.0.0.0, port_value: 9901 }

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8000 }
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route:
                  cluster: grpc_server 
                  timeout: 0s
                  max_stream_duration:
                    grpc_timeout_header_max: 0s
              cors:
                allow_origin_string_match:
                - prefix: "*"
                allow_methods: GET, PUT, DELETE, POST, OPTIONS
                allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
                max_age: "1728000"
                expose_headers: custom-header-1,grpc-status,grpc-message
          http_filters:
          - name: envoy.filters.http.grpc_web
          - name: envoy.filters.http.cors
          - name: envoy.filters.http.router
  clusters:
  - name: grpc_server
    connect_timeout: 0.25s
    type: logical_dns
    http2_protocol_options: {}
    lb_policy: round_robin
    load_assignment:
      cluster_name: cluster_0
      endpoints:
        - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: backend
                    port_value: 50051

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文