2.快速开始---HelloWorld

国际惯例,先从helloworld例子开始,了解一下使用grpc的流程。

第一步 编写proto文件

定义我们的服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
syntax = "proto3";

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;
}

定义服务

使用”service”定义服务,一个服务可以提供多个rpc方法。:

service Greeter { // (Method definitions not shown) }

定义RPC方法

使用”rpc”在服务中定义rpc方法,并指定方法的请求和响应消息类型。

gRPC允许定义4种rpc方法,后面会详细介绍。

客户端可以使用存根调用这个rpc方法,然后等待回应,就像本地调用一样。

rpc SayHello (HelloRequest) returns (HelloReply) {}

定义消息

使用”message”定义所有请求的 protocol buffer 消息类型定义以及在服务方法中使用的响应类型

// The request message containing the user’s name.
message HelloRequest {
string name = 1;
}

// The response message containing the greetings
message HelloReply {
string message = 1;
}

这里使用的都是简单的string类型,后面的”=1”是protocol buffer序列化和反序列化时使用的”key”,后面会专门讲解protocol buffer编码机制。

第二步,生成客户端和服务端代码

python比较顺手,我们以python说明。

上一节讲过,我们现在要使用protoc工具和对应的python插件生成代码,安装好相关工具后,执行以下命令生成代码:

1
> protoc -I ../../protos/ --python_out=. --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_python_plugin` ../../protos/helloworld.proto

会生成2个py文件:helloworld_pb2.py,helloworld_pb2_grpc.py

这2文件的作用分别是:
helloworld_pb2.py:这个文件包含消息定义及protocol buffer编码相关代码

helloworld_pb2_grpc.py:这个文件包含客户端调用存根和服务端的抽象类。

不同语言大都会生成这2类文件。

然后我们使用这2个生成的文件分别编写客户端和服务端代码。

客户端实现:

greeter_client.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from __future__ import print_function

import grpc

import helloworld_pb2
import helloworld_pb2_grpc

def run():
# NOTE(gRPC Python Team): .close() is possible on a channel and should be
# used in circumstances in which the with statement does not fit the needs
# of the code.
with grpc.insecure_channel('localhost:50051') as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'))
print("Greeter client received: " + response.message)

if __name__ == '__main__':
run()

greeter_server.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from concurrent import futures  
import time

import grpc

import helloworld_pb2
import helloworld_pb2_grpc

_ONE_DAY_IN_SECONDS = 60 * 60 * 24

class Greeter(helloworld_pb2_grpc.GreeterServicer):

def SayHello(self, request, context):
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)

def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
server.add_insecure_port('[::]:50051')
server.start()
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop(0)

if __name__ == '__main__':
serve()

第三步 运行

分别运行server,client代码,即可。