gRPC 简介
gRPC 是 Google 开源的一个高性能 RPC 通信框架, 通过 Protocol Buffers https://developers.google.com/protocol-buffers/ 作为其 IDL, 可以在不同语言开发的平台上使用, 同时基于 HTTP/2 协议实现, 继而提供了连接多路复用, 头部压缩, 流控等特性, 极大地提高了客户端与服务端的通信效率.
在 gRPC 里客户端应用可以像本地方法调用一样可以调用到位于不同服务器上的服务端应用方法, 你可以很方便地创建分布式应用和服务. 同其他 RPC 框架一样, gRPC 也需要定义一个服务接口, 同时指定其能够被远程调用的方法和返回类型, 服务端实现这个接口, 同时起一个 gRPC Server 来处理客户端请求, 而客户端则存在一个与服务端方法一样的存根.
环境准备
通过阿里云容器服务控制台申请一个 K8S 集群
安装 grpcurl 工具, 具体可参考这里 https://github.com/fullstorydev/grpcurl
gRPC 访问需要 Ingress Controller 0.15.0-1 及以上支持, 具体可参考发布公告
gRPC 服务示例
我们定义如下服务接口, 客户端可调用 helloworld.Greeter 服务的 SayHello 接口:
- option java_multiple_files = true;
- option java_package = "io.grpc.examples.helloworld";
- option java_outer_classname = "HelloWorldProto";
- package helloworld;
- // The greeting service definition.
- service Greeter {
- // Sends a greeting
- rpc SayHello (HelloRequest) returns (HelloReply) {}
- }
- // The request message containing the user's name.
- message HelloRequest {
- string name = 1;
- }
- // The response message containing the greetings
- message HelloReply {
- string message = 1;
- }
具体测试示例可参考这里 https://github.com/grpc/grpc-go/tree/master/examples .
部署示例服务
1, 部署 gRPC 服务:
- apiVersion: extensions/v1beta1
- kind: Deployment
- metadata:
- name: grpc-service
- spec:
- replicas: 1
- template:
- metadata:
- labels:
- run: grpc-service
- spec:
- containers:
- - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/grpc-server:latest
- imagePullPolicy: Always
- name: grpc-service
- ports:
- - containerPort: 50051
- protocol: TCP
- restartPolicy: Always
- ---
- apiVersion: v1
- kind: Service
- metadata:
- name: grpc-service
- spec:
- ports:
- - port: 50051
- protocol: TCP
- targetPort: 50051
- selector:
- run: grpc-service
- sessionAffinity: None
- type: NodePort
- kubectl apply -f grpc-service.yml
- deployment "grpc-service" created
- service "grpc-service" created
2, 创建 SSL 证书:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=grpc.example.com/O=grpc.example.com"
kubectl create secret tls grpc-secret --key tls.key --cert tls.crt
secret "grpc-secret" created
3, 配置 Ingress 路由规则:
- apiVersion: extensions/v1beta1
- kind: Ingress
- metadata:
- name: grpc-ingress
- annotations:
- # 注意这里: 必须要配置以指明后端服务为 gRPC 服务
- nginx.ingress.kubernetes.io/grpc-backend: "true"
- spec:
- tls:
- - hosts:
- # 证书域名
- - grpc.example.com
- secretName: grpc-secret
- rules:
- # gRPC 服务域名
- - host: grpc.example.com
- http:
- paths:
- - path: /
- backend:
- serviceName: grpc-service
- servicePort: 50051
- kubectl apply -f grpc-ingress.yml
- ingress "grpc-ingress" created
4, 测试 gRPC 服务访问:
4.1, 查看 gRPC 服务端提供的所有服务:
grpcurl -insecure grpc.example.com:443 list
- grpc.reflection.v1alpha.ServerReflection
- helloworld.Greeter
这里我们可以看到服务端提供了 helloworld.Greeter 服务
4.2, 查看 helloworld.Greeter 服务的接口方法:
grpcurl -insecure grpc.example.com:443 list helloworld.Greeter
SayHello
这里可以看到 helloworld.Greeter 服务提供了 SayHello 方法
4.3, 描述 SayHello 方法的具体协议参数:
grpcurl -insecure grpc.example.com:443 describe helloworld.Greeter.SayHello
helloworld.Greeter.SayHello is a method:
- {
- "name": "SayHello",
- "inputType": ".helloworld.HelloRequest",
- "outputType": ".helloworld.HelloReply",
- "options": {
- }
- }
4.4, 调用 SayHello 方法并传递 name 参数:
grpcurl -insecure -d '{"name":"gRPC"}' grpc.example.com:443 helloworld.Greeter.SayHello
- {
- "message": "Hello gRPC"
- }
- grpcurl -insecure -d '{"name":"world"}' grpc.example.com:443 helloworld.Greeter.SayHello
- {
- "message": "Hello world"
- }
灰度发布 gRPC 服务
通过阿里云容器服务 K8S Ingress Controller 实现应用服务的灰度发布一文详细阐述了如何通过 Ingress Controller 来实现应用的灰度发布, 当然我们也支持 gRPC 服务的灰度发布.
注意: 由于 nginx grpc_pass 的限制, 目前对于 gRPC 服务暂不支持 service-weight 配置
1, 部署新版本 gRPC 服务:
- apiVersion: extensions/v1beta1
- kind: Deployment
- metadata:
- name: grpc-service-2
- spec:
- replicas: 1
- template:
- metadata:
- labels:
- run: grpc-service-2
- spec:
- containers:
- - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/grpc-server:latest-2
- imagePullPolicy: Always
- name: grpc-service-2
- ports:
- - containerPort: 50051
- protocol: TCP
- restartPolicy: Always
- ---
- apiVersion: v1
- kind: Service
- metadata:
- name: grpc-service-2
- spec:
- ports:
- - port: 50051
- protocol: TCP
- targetPort: 50051
- selector:
- run: grpc-service-2
- sessionAffinity: None
- type: NodePort
- kubectl apply -f grpc-service-2.yml
- deployment "grpc-service-2" created
- service "grpc-service-2" created
2, 修改 Ingress 路由规则:
- apiVersion: extensions/v1beta1
- kind: Ingress
- metadata:
- name: grpc-ingress
- annotations:
- # 注意这里: 必须要配置以指明后端服务为 gRPC 服务
- nginx.ingress.kubernetes.io/grpc-backend: "true"
- # 将请求头中满足 foo=bar 的请求转发到 grpc-service-2 服务中
- nginx.ingress.kubernetes.io/service-match: 'grpc-service-2: header("foo","bar")'
- spec:
- tls:
- - hosts:
- # 证书域名
- - grpc.example.com
- secretName: grpc-secret
- rules:
- # gRPC 服务域名
- - host: grpc.example.com
- http:
- paths:
- - path: /
- backend:
- serviceName: grpc-service
- servicePort: 50051
- - path: /
- backend:
- serviceName: grpc-service-2
- servicePort: 50051
- kubectl apply -f grpc-ingress-2.yml
- ingress "grpc-ingress" configured
3, 测试 gRPC 服务访问:
- ## 不带 foo=bar 的请求头访问
- grpcurl -insecure -d '{"name":"gRPC"}' grpc.example.com:443 helloworld.Greeter.SayHello
- {
- "message": "Hello gRPC"
- }
- ## 带 foo=bar 的请求头访问
- grpcurl -insecure -rpc-header 'foo: bar' -d '{"name":"gRPC"}' grpc.example.com:443 helloworld.Greeter.SayHello
- {
- "message": "Hello2 gRPC"
- }
来源: https://yq.aliyun.com/articles/598826