React+ GRPC不到达特使容器
我试图在React中构建一个非常基本的网页,该网页将将GRPC请求发送到用Rust编写的后端。
我遵循了这些指南:
但是,我无法获得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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
就您而言,在400或500级别的
HTTP响应
可能是由于您的GRPC服务无法从特使到达。您说特使在码头容器中运行。如果是这样,则在您的Envoy Config:无法达到code> Hellors
,因为您指定地址
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:cannot be reached because you specify the address
0.0.0.0
. Docker containers use their own networks, so inside that network, the0.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.