gRPC学习记录--python
gRPC学习记录
gRPC 是什么?
RPC是远程过程调用(Remote Procedure Call)的缩写,
在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。与许多 RPC 系统类似,gRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。
自己的话就是:它是一种用于不同计算机之间进行通信和调用远程方法的协议。
应用在
- 客户端/服务器通信:允许客户端应用程序通过网络调用位于远程服务器上的方法。
- 分布式系统:在分布式环境下进行通信和协作,允许不同的组件或服务通过RPC调用彼此的方法。
- 微服务架构:在微服务架构中,不同的服务可以通过RPC进行通信,实现服务之间的调用和协作。
- Web开发:RPC协议也可以用于Web开发中,通过将远程方法封装为网络请求,实现客户端与服务器端的通信。
准备:
安装
安装 Git
你可以从http://git-scm.com/download下载和安装 Git。安装好 Git 后,你应该能访问 git 命令行工具。你需要的主要命令如下:
- git clone … : 从远程代码库克隆一份到本机。
- git checkout … : 检出一个特殊分支或一个标签版本的代码来改进。
安装 gRPC
针对你选择的语言构建和安装 gRPC 插件和相关工具,可以参照快速开始。 Java gRPC 除了 JDK 外不需要其他工具。
Python
例子代码在 GitHub 源码库的 examples
目录。你可以运行如下命令克隆源码到本地:
- git clone https://github.com/grpc/grpc.git
切换当前目录到 examples/python/helloworld
- cd examples/python/helloworld/
使用 protocol buffers
需要提前知道的是,gRPC 默认使用 protocol buffers,这是 Google 开源的一套成熟的结构数据序列化机制(当然也可以使用其他数据格式如 JSON)。正如你将在下方例子里所看到的,你用 proto files 创建 gRPC 服务,用 protocol buffers 消息类型来定义方法参数和返回类型。
优点:
- 体积小: protobuf 是一种二进制的格式,相比于 JSON,它的编码后的数据更小。这意味着在网络传输时,使用 protobuf 可以减少带宽的使用量,节约存储空间。
- 解析速度快: protobuf 的编解码过程是直接使用代码生成器生成的高效的代码,因此解析速度更快。而 JSON 的解析是通过解析器根据文本解析的,相对而言较慢。
- 可读性好: JSON 是一种文本格式,易于阅读和调试。相比之下,protobuf 是二进制格式,对人类来说不够友好。
- 可扩展性强: protobuf 支持向后和向前兼容的数据格式演化。当更新数据结构时,旧版本的负载仍然可以被新版本的代码解析,而不会导致解析错误。
不足:
- 平台依赖性: protobuf 在不同的编程语言中使用了不同的库和代码生成器,这导致在不同平台和语言之间可能会存在一些差异。
- 可读性差: 由于 protobuf 是二进制格式,对人类来说难以直接阅读。这在调试或查看数据时可能会造成一些困扰。
- 不支持动态解析: protobuf 消息格式是在编译时定义的,因此不能像 JSON 一样动态解析。这意味着在解析之前,需要知道数据的结构和字段。
- 可移植性有限: protobuf 的消息结构是紧耦合的,不够灵活。这意味着如果某个消息的结构发生变化,那么所有使用该消息的应用程序都需要进行相应的更改。
总结就是:是一种二进制的传出的序列数据结构;比json 更快的更小
Protocol buffers 版本
尽管 protocol buffers 对于开源用户来说已经存在了一段时间,例子内使用的却一种名叫 proto3 的新风格的 protocol buffers,它拥有轻量简化的语法、一些有用的新功能,并且支持更多新语言。当
Hello Worf gRPC!
开始~
定义服务
创建我们例子的第一步是定义一个服务:一个 RPC 服务通过参数和返回类型来指定可以远程调用的方法。我们使用 protocol buffers 接口定义语言来定义服务方法,用 protocol buffer 来定义参数和返回类型。客户端和服务端均使用服务定义生成的接口代码。这里有我们服务定义的例子,在 helloworld.proto 里用 protocol buffers IDL 定义的。Greeter
服务有一个方法 SayHello
,可以让服务端从远程客户端接收一个包含用户名的 HelloRequest
消息后,在一个 HelloReply
里发送回一个 Greeter
。这是你可以在 gRPC 里指定的最简单的 RPC - 你可以在教程里找到针对你选择的语言更多类型的例子。
syntax = "proto3";
option java_package = "io.grpc.examples";
package helloworld;
// The greeter 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;
}
生成 gRPC 代码
一旦定义好服务,我们可以使用 protocol buffer 编译器 protoc
来生成创建应用所需的特定客户端和服务端的代码 - 你可以生成任意 gRPC 支持的语言的代码,当然 PHP 和 Objective-C 仅支持创建客户端代码。生成的代码同时包括客户端的存根和服务端要实现的抽象接口,均包含 Greeter
所定义的方法。
python 实现可以用如下命令生成客户端和服务端:
- ./run_codegen.sh
这内部调用 protocol buffer 编译器:
- protoc -I ../../protos --python_out=. --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_python_plugin` ../../protos/helloworld.proto
这生成了 helloworld_pb2.py
,包含我们生成的客户端和服务端类,此外还有用于填充、序列化、提取 HelloRequest
和 HelloResponse
消息类型的类。
写一个服务器
服务实现
-
Python
[greeter_server.py](http://doc.oschina.net/https://github.com/grpc/grpc/blob/master/examples/python/helloworld/greeter_server.py) 实现了 `Greeter` 服务所需要的行为。 正如你所见,`Greeter` 类通过实现 `sayHello` 方法,实现了从 proto 服务定义生成的`helloworld_pb2.BetaGreeterServicer` 接口: ```python
class Greeter(helloworld_pb2.BetaGreeterServicer):
def SayHello(self, request, context):
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
```为了返回给客户端应答并且完成调用: 1. 用我们的激动人心的消息构建并填充一个在我们接口定义的 `HelloReply` 应答对象。 2. 将 `HelloReply` 返回给客户端。
服务端实现
需要提供一个 gRPC 服务的另一个主要功能是让这个服务实在在网络上可用。
-
Python
[greeter_server.py](http://doc.oschina.net/https://github.com/grpc/grpc/blob/master/examples/python/helloworld/greeter_server.py) 提供了以下代码作为 Python 的例子。 ```
server = helloworld_pb2.beta_create_Greeter_server(Greeter())
server.add_insecure_port('[::]:50051')
server.start()
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop()
```
在这里我们创建了合理的 gRPC 服务器,将我们实现的 Greeter
服务绑定到一个端口。然后我们启动服务器:服务器现在已准备好从 Greeter
服务客户端接收请求。我们将在具体语言对应的文档里更深入地了解这所有的工作是怎样进行的。
写一个客户端
客户端的 gRPC 非常简单。在这一步,我们将用生成的代码写一个简单的客户程序来访问我们在上一节里创建的 Greeter
服务器。 同样,我们也不打算对如何实现一个客户端程序深入更多,我们把这些内容放到教程里。
连接服务
首先我们看一下我们如何连接 Greeter
服务器。我们需要创建一个 gRPC 频道,指定我们要连接的主机名和服务器端口。然后我们用这个频道创建存根实例。
-
Python
生成的 Python 代码有一个根据频道创建存根的帮助方法。 ```py
channel = implementations.insecure_channel('localhost', 50051)
stub = helloworld_pb2.beta_create_Greeter_stub(channel)
...
```
调用 RPC
现在我们可以联系服务并获得一个 greeting :
- 我们创建并填充一个
HelloRequest
发送给服务。 - 我们用请求调用存根的
SayHello()
,如果 RPC 成功,会得到一个填充的HelloReply
,从其中我们可以获得 greeting。
-
Python
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'), _TIMEOUT_SECONDS) print "Greeter client received: " + response.message
你可以在 [greeter_client.py](http://doc.oschina.net/https://github.com/grpc/grpc/blob/master/examples/python/helloworld/greeter_client.py) 里查看完整的客户端代码。
试一下!
你可以尝试用同一个语言在客户端和服务端构建并运行例子。或者你可以尝试 gRPC 最有用的一个功能 - 不同的语言间的互操作性,即在不同的语言运行客户端和服务端。每个服务端和客户端使用从同一过 proto 文件生成的接口代码,则意味着任何 Greeter
客户端可以与任何 Greeter
服务端对话。
-
Python 你可以用如下命令到
examples/python/helloworld
下运行服务端:`$ ./run_server.sh` 就是需要自己分别启动 服务端 以及 客户端
总结一下就是 通过 编写 服务)(.protoc 文件 ) 通过 服务生成对应的代码 再编写对应的服务端的具体内容 然后 实现对 客户端的服务