.NET网关与Gateway实战-Envoy与kong课程
Envoy实现.NET架构的网关(一)静态配置与文件动态配置
Envoy实现.NET架构的网关(二)基于控制平面的动态配置
什么是GRPC
gRPC是一种与语言无关的高性能远程过程调用 (RPC) 框架。gRPC 的主要好处是:
现代、高性能、轻量级的 RPC 框架。
契约优先的 API 开发,默认使用协议缓冲区,与语言无关的实现。
可用于多种语言的工具来生成强类型服务器和客户端。
支持客户端、服务器和双向流调用。
通过 Protobuf 二进制序列化减少网络使用。
这些优势使 gRPC 非常适合:
效率至关重要的轻量级微服务。
需要多种语言进行开发的多语言系统。
需要处理流请求或响应的点对点实时服务。
什么是grpc-json转码器
grpc-json转码器是Envoy中的一个过滤器,它允许 RESTful JSON API 客户端通过 HTTP 向 Envoy 发送请求并代理到 gRPC 服务。
大家可以参考envoy官方文档:https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/grpc_json_transcoder_filter
下面我们来通过Envoy的grpc-json转码器实现grpc服务的代理。
创建grpc服务
.NET中的grpc可以参考官方文档来实现。我们通过vs创建两个默认的grpc server:GrpcService1与GrpcService2,来实现grpc的负载。
我们需要基于默认Grpc模板项目做出以下修改
固定Grpc的端口,修改GrpcService1的默认端口为6001
固定Grpc的端口,修改GrpcService2的默认端口为6002
为了判断是否实现负载,我们修改GrpcService1的SayHello方法返回体,让其返回字符串Hello 1
为了判断是否实现负载,我们修改GrpcService2的SayHello方法返回体,让其返回字符串Hello 2
public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseUrls("http://*:6001").UseStartup<Startup>();});public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseUrls("http://*:6002").UseStartup<Startup>();});public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context){return Task.FromResult(new HelloReply{Message = "Hello 1 " + request.Name});}public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context){return Task.FromResult(new HelloReply{Message = "Hello 2 " + request.Name});}
修改完之后我们启动两个Grpc Server
Grpc服务描述符
Envoy必须知道GRPC服务的proto描述符才能REST API转码,我们可以通过以下链接下载proto工具 https://github.com/protocolbuffers/protobuf/releases
下载完成之后,通过以下命令生成描述符,生成的描述符需要和配置文件一起挂载进容器
protoc.exe --descriptor_set_out=C:\greet.pb --include_imports C:\greet.proto --proto_path=C://
配置Envoy
Grpc相关的配置可以参考官方文档,其中需要注意的是以下几点
我们需要将dns_type改为static,因为我们grpc用的是ip而不是域名
并且需要指定auto_mapping: true,这样就可以在我们没有设置http method的情况下路由到我们的grpc服务中的方法
指定grpc描述符,让Envoy知道grpc定义
具体配置如下
admin:address:socket_address: {address: 0.0.0.0, port_value: 9901}static_resources:listeners:- name: listener1address:socket_address: {address: 0.0.0.0, port_value: 10000}filter_chains:- filters:- name: envoy.filters.network.http_connection_managertyped_config:"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManagerstat_prefix: grpc_jsoncodec_type: AUTOroute_config:name: local_routevirtual_hosts:- name: local_servicedomains: ["*"]routes:- match: {prefix: "/greet.Greeter"}route: {cluster: grpc, timeout: 60s}http_filters:- name: envoy.filters.http.grpc_json_transcodertyped_config:"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoderproto_descriptor: "/etc/envoy/greet.pb"services: ["greet.Greeter"]print_options:add_whitespace: truealways_print_primitive_fields: truealways_print_enums_as_ints: falsepreserve_proto_field_names: falseauto_mapping: true- name: envoy.filters.http.routerclusters:- name: grpctype: staticlb_policy: ROUND_ROBINdns_lookup_family: V4_ONLYtyped_extension_protocol_options:envoy.extensions.upstreams.http.v3.HttpProtocolOptions:"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptionsexplicit_http_config:http2_protocol_options: {}load_assignment:cluster_name: grpcendpoints:- lb_endpoints:- endpoint:address:socket_address:address: 192.168.43.94port_value: 6001- endpoint:address:socket_address:address: 192.168.43.94port_value: 6002
启动Envoy
需要特别注意的是,我们需要将envoy.yaml和描述文件都映射到我们的容器内
docker run --rm -it -p 9902:9902 -p 10000:10000 -v D:/gateway/envoy/config/grpc/:/etc/envoy/ -v D:/gateway/envoy/logs:/logs envoyproxy/envoy-dev -c /etc/envoy/envoy.yaml
测试
测试的时候需要注意的是
转码器过滤器处理的请求路径规则是/<package>.<service>/<method>
我们需要使用POST方法。
通过postman调用接口来看,我们成功利用GRPC-Json转码器实现了grpc的代理,并实现了grpc的负载!!