React+ GRPC不到达特使容器

发布于 2025-01-24 19:13:13 字数 6377 浏览 5 评论 0原文

我试图在React中构建一个非常基本的网页,该网页将将GRPC请求发送到用Rust编写的后端。

我遵循了这些指南:

https://daily.daily.daily.daily.daily.daily.daily.daily.daily.daily /blog/build-a-chat-app-using-grpc-and-reactjs

https://github.com/grpc/grpc/grpc/grpc/grpc-web/tree/master/master/net/grpc/gateway/gateway/examples/helloworld

但是,我无法获得GRPC请求到达Docker容器中的特使代理(Envoy是迄今为止在容器中运行的唯一组件)。

这是我的原始文件:

syntax = "proto3";

package Base;

service Hello {
    rpc HelloWorld(HelloRequest) returns (HelloResponse) {}
}

message HelloRequest {}
message HelloResponse {
    string message = 1;
}

这是我的app.js文件(基本上是由React Boottrapper创建的,我只是添加了功能和按钮)

import logo from './logo.svg';
import './App.css';

import { HelloClient } from './base_grpc_web_pb';
import { HelloRequest } from './base_pb';

const client = new HelloClient("http://" + window.location.hostname + ":8080", null, null);

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
      <button
        onClick={sendRequest}
        style={{
          padding: "7px 38px",
          fontSize: "1.2em",
          boxSizing: "content-box",
          borderRadius: "4px",
        }}
      >
        Join
      </button>
    </div>
  );
}

function sendRequest() {
  const request = new HelloRequest();
  
  console.log("CLICK");

  client.helloWorld(request, {}, (err, response) => {
    if (err) return console.log("BBBBB error", err);
    console.log("AAAAA RESPONSE", response.getMessage());
  });
}


export default App;

这是我的特使配置(我在Ubuntu 22.04上,因此无需覆盖带有host.docker.internal的地址):

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

static_resources:
  listeners:
    - name: proxy
      address:
        socket_address: { address: 0.0.0.0, port_value: 8080 }
      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: hellors
                            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
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
                  - name: envoy.filters.http.cors
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
                  - name: envoy.filters.http.router
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
    - name: hellors
      connect_timeout: 0.25s
      type: logical_dns
      http2_protocol_options: {}
      lb_policy: round_robin
      # win/mac hosts: Use address: host.docker.internal instead of address: localhost in the line below
      load_assignment:
        cluster_name: cluster_0
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: 0.0.0.0
                      port_value: 9090

dockerfile for Envoy:

FROM envoyproxy/envoy-dev:latest
COPY envoy.yaml /etc/envoy/envoy.yaml
RUN chmod go+r /etc/envoy/envoy.yaml

在控制台中,在我单击按钮后,我会收到此错误消息:

http://localhost:8080/Base.Hello/HelloWorld [HTTP/1.1 503 Service Unavailable 5ms]

接下来,

message: "Http response at 400 or 500 level", [...]

如果我尝试curl curl端口,似乎``t linking:

>$ curl -v http://localhost:8080
*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 503 Service Unavailable
< content-length: 145
< content-type: text/plain
< date: Thu, 28 Apr 2022 16:03:55 GMT
< server: envoy
< 
* Connection #0 to host localhost left intact
upstream connect error or disconnect/reset before headers. reset reason: connection failure, transport failure reason: delayed connect error: 111

在这一点上,我很困惑,所有配置文件似乎都还可以,但我仍然无法达到特使代理。有什么建议吗?

我偶然发现了这篇文章建议使用nginx,但是I不明白为什么需要这一点,尤其是因为我正在查看的GRPC示例不使用它。

I was trying to build a very basic web page in React that would send gRPC request to a backend written in Rust.

I followed these guides:

https://daily.dev/blog/build-a-chat-app-using-grpc-and-reactjs

https://github.com/grpc/grpc-web/tree/master/net/grpc/gateway/examples/helloworld

However, I cannot get the gRPC request to reach the envoy proxy in the docker container (envoy is the only component running inside a container so far).

This is my proto file:

syntax = "proto3";

package Base;

service Hello {
    rpc HelloWorld(HelloRequest) returns (HelloResponse) {}
}

message HelloRequest {}
message HelloResponse {
    string message = 1;
}

This is my App.js file (basically as it gets created by the react bootstrapper, I just added the function and the button)

import logo from './logo.svg';
import './App.css';

import { HelloClient } from './base_grpc_web_pb';
import { HelloRequest } from './base_pb';

const client = new HelloClient("http://" + window.location.hostname + ":8080", null, null);

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
      <button
        onClick={sendRequest}
        style={{
          padding: "7px 38px",
          fontSize: "1.2em",
          boxSizing: "content-box",
          borderRadius: "4px",
        }}
      >
        Join
      </button>
    </div>
  );
}

function sendRequest() {
  const request = new HelloRequest();
  
  console.log("CLICK");

  client.helloWorld(request, {}, (err, response) => {
    if (err) return console.log("BBBBB error", err);
    console.log("AAAAA RESPONSE", response.getMessage());
  });
}


export default App;

This is my envoy configuration (I am on Ubuntu 22.04, so no need to override the address with host.docker.internal):

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

static_resources:
  listeners:
    - name: proxy
      address:
        socket_address: { address: 0.0.0.0, port_value: 8080 }
      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: hellors
                            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
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
                  - name: envoy.filters.http.cors
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
                  - name: envoy.filters.http.router
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
    - name: hellors
      connect_timeout: 0.25s
      type: logical_dns
      http2_protocol_options: {}
      lb_policy: round_robin
      # win/mac hosts: Use address: host.docker.internal instead of address: localhost in the line below
      load_assignment:
        cluster_name: cluster_0
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: 0.0.0.0
                      port_value: 9090

Dockerfile for envoy:

FROM envoyproxy/envoy-dev:latest
COPY envoy.yaml /etc/envoy/envoy.yaml
RUN chmod go+r /etc/envoy/envoy.yaml

In the console, after I click the button I get this error message:

http://localhost:8080/Base.Hello/HelloWorld [HTTP/1.1 503 Service Unavailable 5ms]

Followed by

message: "Http response at 400 or 500 level", [...]

If I try to curl the port it seems like it isn't listening:

>$ curl -v http://localhost:8080
*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 503 Service Unavailable
< content-length: 145
< content-type: text/plain
< date: Thu, 28 Apr 2022 16:03:55 GMT
< server: envoy
< 
* Connection #0 to host localhost left intact
upstream connect error or disconnect/reset before headers. reset reason: connection failure, transport failure reason: delayed connect error: 111

At this point I am quite stuck, all the configuration files seem ok, yet I still can't reach the envoy proxy. Any suggestions?

I have stumbled upon this post that suggests to use nginx, however I don't understand why that would be needed, especially since the gRPC examples I was looking at don't use it.

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦在深巷 2025-01-31 19:13:13

就您而言,在400或500级别的HTTP响应可能是由于您的GRPC服务无法从特使到达。

您说特使在码头容器中运行。如果是这样,则在您的Envoy Config:无法达到code> Hellors

clusters:
- name: hellors
  load_assignment:
    endpoints:
    - lb_endpoints:
      - endpoint:
          address:
            socket_address:
              address: 0.0.0.0
              port_value: 9090

,因为您指定地址0.0.0.0.0。 Docker容器使用自己的网络,因此在该网络内部,0.0.0.0:9090未定义,因为您的GRPC服务在主机上运行。

您可能需要尝试在主机网络(-NET =主机)中运行Envoy。

或者,如果您的GRPC服务可以设置为容器,则可以在同一Docker网络中运行Envoy GRPC服务。

In your case, the Http response at 400 or 500 level is probably caused by the fact that your gRPC service is not reachable from Envoy.

You said that Envoy is running in a Docker container. If so, the cluster hellors in your Envoy config:

clusters:
- name: hellors
  load_assignment:
    endpoints:
    - lb_endpoints:
      - endpoint:
          address:
            socket_address:
              address: 0.0.0.0
              port_value: 9090

cannot be reached because you specify the address 0.0.0.0. Docker containers use their own networks, so inside that network, the 0.0.0.0:9090 is not defined, because your gRPC service is running on your host.

You may want to try running Envoy in your host network (--net=host).

Or if your gRPC service can be containerized, you can run Envoy and the gRPC service in the same Docker network.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文