首页 服务网格 ASM ASM网关 入口网关 多协议支持 通过ASM入口网关实现HTTP请求网格内gRPC服务

通过ASM入口网关实现HTTP请求网格内gRPC服务

ASM入口网关支持协议转码的能力。客户端可以使用HTTP/JSON访问服务网格内的gRPC服务。本文介绍如何通过ASM入口网关实现HTTP请求网格内gRPC服务。

前提条件

背景信息

Envoy作为服务网格ASM数据平面的Proxy组件,内置多种HTTP扩展过滤器,包括HTTP到gRPC的转码器。为了启用该过滤器,Envoy定义了相应的过滤器协议。ASM的控制平面需要定义一个EnvoyFilter来声明某个阶段启用这个过滤器,然后下发该EnvoyFilter在指定环节启用转码器。

转码流程

ASM入口网关可将HTTP/JSON转码为gRPC。下图为完整的HTTP请求、gRPC转码以及gRPC请求流程。请求流程

序号

说明

ASM控制平面下发用于gRPC转码的EnvoyFilter,用于路由到gRPC服务端口的规则配置Gateway和VirtualService到ASM入口网关,入口网关接收后即时加载生效。

入口网关收到客户端HTTP协议的请求后,将进行路由规则匹配和协议转换,然后以gRPC协议请求服务网格内的gRPC服务。

入口网关收到后端服务的gRPC响应,再将其转换为HTTP的响应返回给请求方。

步骤一:部署示例应用

  1. 创建grpc-best命名空间,开启自动注入,并同步自动注入至Kubernetes集群。

    1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理
    2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择网格实例 > 全局命名空间
    3. 全局命名空间页面单击新建,然后在新建命名空间面板,配置名称grpc-best,单击确定

    4. 操作列,单击grpc-best对应的启用 Sidecar 自动注入,在确认对话框,单击确定

    5. 在页面上方,单击同步自动注入至Kubernetes集群

  2. 在数据面集群的grpc-best命名空间中部署一个可访问的gRPC服务。

    1. 使用以下YAML,创建grpc-server.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        namespace: grpc-best
        name: grpc-server-java
        labels:
          app: grpc-server-deploy
          version: v1
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: grpc-server-deploy
            version: v1
        template:
          metadata:
            labels:
              app: grpc-server-deploy
              version: v1
          spec:
            serviceAccountName: grpc-best-sa
            containers:
              - name: grpc-server-deploy
                image: feuyeux/grpc_with_api_server_java:1.0.0
                imagePullPolicy: Always
                ports:
                  - containerPort: 9996
                    name: grpc-port
      ---
      apiVersion: v1
      kind: Service
      metadata:
        namespace: grpc-best
        name: grpc-server-svc
        labels:
          app: grpc-server-svc
      spec:
        ports:
          - port: 9996
            name: grpc-port
        selector:
          app: grpc-server-deploy
    2. 执行以下命令,部署gRPC服务。

      kubectl apply -f grpc-server.yaml
  3. 在ASM实例中创建网关规则、虚拟服务和目标规则。

    1. 使用以下内容,创建gateway-sr-vs.yaml

      本示例的ASM网关名称为ingressgateway

      apiVersion: networking.istio.io/v1alpha3
      kind: Gateway
      metadata:
        namespace: grpc-best
        name: grpc-gateway
      spec:
        selector:
          istio: ingressgateway
        servers:
          - port:
              number: 9996
              name: grpc
              protocol: GRPC
            hosts:
              - "*"
      ---
      apiVersion: networking.istio.io/v1alpha3
      kind: VirtualService
      metadata:
        namespace: grpc-best
        name: grpc-server-vs
      spec:
        hosts:
          - "*"
        gateways:
          - grpc-gateway
        http:
          - match:
              - port: 9996
            route:
              - destination:
                  host: grpc-server-svc
                  subset: v1
                weight: 100
      ---
      apiVersion: networking.istio.io/v1alpha3
      kind: DestinationRule
      metadata:
        namespace: grpc-best
        name: grpc-server-dr
      spec:
        host: grpc-server-svc
        subsets:
          - name: v1
            labels:
              version: v1
          - name: v2
            labels:
              version: v2
          - name: v3
            labels:
              version: v3
          - name: v4
            labels:
              version: v4
          - name: v5
            labels:
              version: v5
    2. 执行以下命令,部署网关规则、虚拟服务和目标规则。

      kubectl apply -f gateway-sr-vs.yaml

步骤二:补充转码声明,生成Proto Descriptors文件

您可以修改服务的.proto文件,使用gRPC协议实现gRPC请求转码成HTTP请求。

  1. .proto文件的实践方法中增加支持转码的声明,以支持HTTP转码gRPC。

    option(google.api.http) = {
      get: "/v1/talk/{data}/{meta}"
    };

    以hello-servicemesh-rpc示例中的.proto为例,补充转码声明后的.proto如下。关于hello-servicemesh-grpc的详细信息,请参见hello-servicemesh-grpc

    import "google/api/annotations.proto";
    service LandingService {
      //Unary RPC
      rpc talk (TalkRequest) returns (TalkResponse) {
        option(google.api.http) = {
          get: "/v1/talk/{data}/{meta}"
        };
      }
    ...
    }
    
    message TalkRequest {
      string data = 1;
      string meta = 2;
    }
  2. googleapishello-servicemesh-grpc克隆到本地。

  3. 在Protocol工具上执行以下命令,使用protoc命令从landing.proto生成landing.proto-descriptor文件。

    # https://github.com/AliyunContainerService/hello-servicemesh-grpc
    proto_path={path/to/hello-servicemesh-grpc}/grpc/proto
    #  https://github.com/googleapis/googleapis/tree/master/
    proto_dep_path={path/to/googleapis}
    
    protoc \
        --proto_path=${proto_path} \
        --proto_path=${proto_dep_path} \
        --include_imports \
        --include_source_info \
        --descriptor_set_out=landing.proto-descriptor \
        "${proto_path}"/landing.proto

步骤三:启用协议转码插件

ASM控制台内置了ASM网关HTTP-gRPC协议转码插件,便于您进行相关配置。

  1. 使用以下Python脚本,将landing.proto-descriptor文件进行Base64编码。

    import base64
    with open("landing.proto-descriptor", 'rb') as fin, open("encoded.txt", 'w', encoding='utf-8') as fout:
        proto = fin.read()
        encoded = base64.b64encode(proto)
        fout.write(bytes.decode(encoded))
    # 最终在encoded.txt文件中拷贝Base64编码后的结果。
  2. 配置ASM网关HTTP-gRPC协议转码。

    1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理
    2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择插件扩展中心 > 插件市场
    3. 插件市场页面,单击ASM网关HTTP-gRPC协议转码卡片,然后单击插件配置页签。

    4. 插件配置页签的插件生效范围区域,单击网关生效,单击添加网关生效范围,选中目标网关(本示例为ingressgateway),单击添加,然后单击确定

    5. 插件配置区域,配置YAML,然后打开生效开关

      YAML字段说明如下。

      字段

      类型

      是否必选

      默认值

      说明

      port_number

      string

      -

      配置需要在网关上进行协议转码的服务端口。

      proto_services

      string array

      ["org.feuyeux.grpc.LandingService"]

      配置在Proto文件中声明的服务,格式为{包名}.{服务名},例如"org.feuyeux.grpc.LandingService"

      proto_descriptor

      string

      -

      生成Proto Descriptor文件后,将文件内容进行Base64编码后的结果。

步骤四:使用HTTP请求网格内的gRPC服务

执行以下命令,通过HTTP请求访问网关的9996端口(该端口暴露了一个gRPC服务)。

curl http://$INGRESS_IP:9996/v1/talk/0/java

预期输出:

{
  "status": 200,
  "results": [
    {
      "id": "69988257608****",
      "type": "OK",
      "kv": {
        "data": "Hello",
        "meta": "JAVA",
        "id": "8c175d5c-d8a3-4197-a7f8-****",
        "idx": "0"
      }
    }
  ]
}

该JSON由后端的gRPC服务返回,表明使用HTTP请求通过ASM网关访问网格内的gRPC服务成功。

阿里云首页 服务网格 相关技术圈