gRPC简介
gRPC是Google开源的一个高性能RPC通信框架,通过Protocol Buffers作为其IDL,可以在不同语言开发的平台上使用,同时基于HTTP/2协议实现,继而提供了连接多路复用、头部压缩、流控等特性,极大地提高了客户端与服务端的通信效率。
在gRPC里客户端应用可以像本地方法调用一样可以调用到位于不同服务器上的服务端应用方法,你可以很方便地创建分布式应用和服务。同其他RPC框架一样,gRPC也需要定义一个服务接口,同时指定其能够被远程调用的方法和返回类型,服务端实现这个接口,同时起一个gRPC Server来处理客户端请求,而客户端则存在一个与服务端方法一样的存根。
环境准备
- 通过阿里云容器服务控制台申请一个K8S集群
- 安装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;
}
具体测试示例可参考这里。
部署示例服务
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/backend-protocol: "GRPC"
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/backend-protocol: "GRPC"
# 将请求头中满足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"
}