Envoy實現.NET架構的網關(三)代理GRPC

什麼是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: listener1
    address:
      socket_address: {address: 0.0.0.0, port_value: 10000}
    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
          stat_prefix: grpc_json
          codec_type: AUTO
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match: {prefix: "/greet.Greeter"}
                route: {cluster: grpc, timeout: 60s}
          http_filters:
          - name: envoy.filters.http.grpc_json_transcoder
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder
              proto_descriptor: "/etc/envoy/greet.pb"
              services: ["greet.Greeter"]
              print_options:
                add_whitespace: true
                always_print_primitive_fields: true
                always_print_enums_as_ints: false
                preserve_proto_field_names: false
              auto_mapping: true
          - name: envoy.filters.http.router

  clusters:
  - name: grpc
    type: static
    lb_policy: ROUND_ROBIN
    dns_lookup_family: V4_ONLY
    typed_extension_protocol_options:
      envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
        "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
        explicit_http_config:
          http2_protocol_options: {}
    load_assignment:
      cluster_name: grpc
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 192.168.43.94
                port_value: 6001
        - endpoint:
            address:
              socket_address:
                address: 192.168.43.94
                port_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的負載!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章