I tried to integrate gPRC into flutter-web, but it always failed. I don't know if there is a problem with my code or GRPC can't be integrated into flutter-web.
dependencies:
flutter:
sdk: flutter
grpc: ^2.1.3
protobuf: ^1.0.1
Here's my server-side code:
I have two questions.
The first one is whether the GRPC can be integrated into fluter-web.?
The second one is what libraries I need and whether there are any examples?
thank you.
The short answer, yes you can.
For now, grpc-web need a web proxy in front of the gRPC server to translate the requests and responses to something the browser can use. See https://grpc.io/blog/state-of-grpc-web/ for details.
You can use Envoy as the web proxy.
Here the steps to use envoy:
set your web client channel in flutter
GrpcWebClientChannel.xhr(Uri.parse('http://localhost:8080'));
set the server to listen on the following sample:
path := "127.0.0.1:3001"
Install envoy from https://www.envoyproxy.io/
create configuration for envoy like the following example. Save it as 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: 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: greeter_service
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,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
max_age: "1728000"
expose_headers: id,token,grpc-status,grpc-message
http_filters:
- name: envoy.filters.http.grpc_web
- name: envoy.filters.http.cors
- name: envoy.filters.http.router
clusters:
- name: greeter_service
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: 3001
Run envoy with the configuration (sample in Linux box):
$ envoy -c envoy.yaml
Now, try to run the flutter web client and server.
See https://github.com/sigurdm/grpc_web_flutter_example or https://github.com/grpc/grpc-web/tree/master/net/grpc/gateway/examples/helloworld
Related
I have grpc server, web application and mobile application. With web application, I used envoy proxy for reverse from grpc web to grpc server by my domain. But this only grpc web can connect to my server over envoy, my application run with grpc cannot connect it. I want to connect to my gprc server over my domain with both grpc-web and grpc. Any one can help me explain and solve this issue. Thanks every one
This is my envoy setup
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: 9090 }
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: echo_service
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: echo_service
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: server
port_value: 8080
Not sure what is the exact question? Currently you need to use Envoy to translate grpc-web to grpc.
I'm currently trying to set up envoy to take in a https request, and pass the request on as an http request to a separately running(via Docker) local endpoint(Envoy is also being run locally). Unfortunately, when I make the request via Postman I get the following error "upstream connect error or disconnect/reset before headers. reset reason: connection failure". Any ideas on how this issue could be fixed?
The envoy.yaml file I'm using is the following:
# envoy
static_resources:
listeners:
- name: "listener"
address: { socket_address: { address: 0.0.0.0, port_value: 8443 } }
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_https
http_filters: { name: envoy.filters.http.router }
route_config:
name: route
virtual_hosts:
- name: host
domains: ["*"]
routes:
- match: { prefix: "/" }
route:
cluster: cluster
timeout: 10s
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"#type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificates:
- certificate_chain: { filename: "/etc/envoy/cert.crt" }
private_key: { filename: "/etc/envoy/cert.key" }
alpn_protocols: "h2,http/1.1"
clusters:
- name: cluster
connect_timeout: 20s
type: strict_dns
lb_policy: least_request
health_checks:
timeout: 5s
interval: 2s
unhealthy_threshold: 3
healthy_threshold: 1
http_health_check: { path: "/healthcheck" }
circuit_breakers:
thresholds:
max_retries: 300
load_assignment:
cluster_name: cluster
endpoints:
- lb_endpoints:
- endpoint: { address: { socket_address: { address: "0.0.0.0", port_value: 8080 } } }
If anything else is needed please let me know. Thanks in advance for the help/tips!
Increase your cluster connect_timeout and try again. Maybe that will fix the problem.
I am trying to deploy 2 services by using the envoy front proxy configuration from envoy github page
My first service is the main site which should work under “/” and the second service is back office administration that should work under “/admin”. The problem starts when I declare the prefix of my first service as “/”. After that Envoy doesn’t route traffic to my admin service at all.
my front-envoy.yaml is:
static_resources:
listeners:
- address:
socket_address:
address: 0.0.0.0
port_value: 80
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: backend
domains:
- “*”
routes:
- match:
prefix: “/”
route:
cluster: service1
- match:
prefix: “/admin”
route:
cluster: service2
http_filters:
- name: envoy.router
config: {}
clusters:
- name: service1
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
http2_protocol_options: {}
hosts:
- socket_address:
address: service1
port_value: 80
- name: service2
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
http2_protocol_options: {}
hosts:
- socket_address:
address: service2
port_value: 80
admin:
access_log_path: “/dev/null”
address:
socket_address:
address: 0.0.0.0
port_value: 8001
Please advice.
The problem is you have "/" as the first prefix matcher, "/" as a prefix will match with all the requests, it will match "/" requests as well as the "/admin" requests. Change the order of your matches to have "/admin" first and then "/". It should work fine.
I'm using Istio pilot-agent proxy in OpenShift cluster.
I have an error (INVALID_ARGUMENT:static_resources.clusters[0].hosts[0]: invalid name url: Cannot find field....
Config:
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
stat_prefix: egress_http
use_remote_address: true
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: local-services
domains: ["*"]
routes:
- match: { prefix: "/service-a" }
route: { cluster: service-a }
http_filters:
- name: envoy.router
clusters:
- name: service-a
connect_timeout: 0.25s
# dns_lookup_family: V4_ONLY
lb_policy: round_robin
type: strict_dns
hosts:
- url : tcp://service-a.apps-stage.vm.mos.cloud.sbrf.ru:80
From what I can tell with Envoy, the error "Cannot find field" means that you requested a field name (in this case, url) in a data structure, but Envoy doesn't support that field name in that data structure.
The "hosts" block, in your example, would look like:
hosts:
- socket_address:
address: "service-a.apps-stage.vm.mos.cloud.sbrf.ru"
port_value: 80
I'm trying to build a service mesh with Istio. Currently I have a Docker-Compose with two REST-services and one sidecar (Envoy) for each. If you send a HTTP-request to serviceA, it is forwarded to serviceB, which returns the result. It works fine. Because the control plane is not implemented yet, the "mesh" is realized using the Envoy-configuration. The config files look as following:
ServiceA:
static_resources:
listeners:
- address:
socket_address:
address: 0.0.0.0
port_value: 80
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: service
domains:
- "*"
routes:
- match:
prefix: "/abc"
route:
prefix_rewrite: "/v1/abc"
host_rewrite: serviceB
cluster: service_ner
http_filters:
- name: envoy.router
config: {}
clusters:
- name: service_abc
connect_timeout: 0.25s
type: logical_dns
dns_lookup_family: V4_ONLY
lb_policy: round_robin
hosts:
- socket_address:
address: serviceB
port_value: 80
admin:
access_log_path: "/dev/null"
address:
socket_address:
address: 0.0.0.0
port_value: 8081
Service B:
static_resources:
listeners:
- address:
socket_address:
address: 0.0.0.0
port_value: 80
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: service
domains:
- "*"
routes:
- match:
prefix: "/"
route:
cluster: local_service
http_filters:
- name: envoy.router
config: {}
clusters:
- name: local_service
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
hosts:
- socket_address:
address: 127.0.0.1
port_value: 5001
admin:
access_log_path: "/dev/null"
address:
socket_address:
address: 0.0.0.0
port_value: 8081
Now I want to implement Istio as control plane and I'm trying to replace a part of the configuration using the Istio-Pilot. Is it possible to overwrite the route rules from the Envoy config files by implementing Istio-route rules? For example:
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: ruleSerA
spec:
destination:
name: serviceA
precedence: 2
route:
- labels:
version: v1
---
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: ruleSerB
spec:
destination:
name: serviceB
precedence: 2
match:
request:
headers:
uri:
prefix: /abc
rewrite:
uri: /v1/abc
route:
- labels:
version: v1
What else do I need to configure to connect the data plane with the service plane? Until now the Istio-route rules did not affect the services at all.
Best regards, Martin