What is rpc? What is grpc?
What is RPC
Remote Procedure Call Protocol RPC (Remote Procedure Call Protocol)
RPC refers to remote procedure call, that is to say, two servers A and B, an application deployed on server A, wants to call the function/method provided by the application on server B, because It is not in the same memory space and cannot be called directly. It needs to express the semantics of the call and convey the data of the call through the network.
For example: in service a, call the get method in the ticket service of service b, then call b directly in service a. ticket.get() to call directly
Without knowing the details of the call, the client calls an object that exists on the remote computer, just like calling an object in the local application.
what is grpc
gRPC (Google Remote Procedure Call) is a high-performance, general-purpose open source RPC framework. It is designed by Google mainly for mobile application development and based on the HTTP/2 protocol standard. It is developed based on the ProtoBuf (Protocol Buffers) serialization protocol and supports many Development languages (python, golang, javascript, C, C++, Node.js, Ruby, Objective-C, PHP and C#, etc.).
gRPC provides an easy way to precisely define services and automatically generate a library of highly reliable client functions for iOS, Android, and backend services . The client takes full advantage of advanced streaming and linking features, which help save bandwidth, reduce the number of TCP connections, save CPU usage, and battery life.
RESTful | gRPC | |
---|---|---|
Full Name | REpresentational State Transfer | Google Remote Procedure Call |
Payload | Readable Data (typically JSON) | Unreadable Binary Data (Protobuf) |
HTTP | HTTP 1.1/HTTP 2 | HTTP/2 |
Performance | Slower | Faster |
Type Safety | No | Yes |
Cross Language | Yes | Yes |
Client Setup | Required | Not required |
Supported Functions | GET/PUT/DELETE/POST/... | Any function |
// Client side
// Student student = Call(ServerAddr, addAge, student)
1. Map this call to Call ID.
2. Serialize the Call ID, student (params), and pack it in binary form
3. Send the data packet obtained in 2 to ServerAddr, which needs to use the network transport layer
4. Wait for the server to return the result
5. If the server call is successful, then Deserialize the result and assign it to the student, and update the age
// Server side
1. Maintain a mapping call_id_map from Call ID to function pointer locally, you can use Map<String, Method> callIdMap
2. Wait for client request
3. After getting a request, deserialize its data packet to get Call ID
4. Find the corresponding function pointer by searching in callIdMap
5. After deserializing the student (params), call the addAge() function locally to get the result
6. Serialize the student result and return it to the Client through the network
what is protobuf
protobuf (Google Protocol Buffers) is an efficient protocol data exchange format tool library (similar to Json) provided by Google, but compared to Json, Protobuf has higher conversion efficiency, time efficiency and space efficiency are 3-5 of JSON Double
is cross-language: python golang java c++ javascript and so on
Generate python client and server
install dependencies
安装依赖:
pip install grpcio
pip install grpcio-tools
pip install protobuf
转化proto文件成client和server
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. wenet.proto
// 文件名 hello.proto,proto版本
syntax = "proto3";
package hello;
// 定义服务
service Greeter {
// 发送数据
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// 请求消息,包含用户的姓名。
message HelloRequest {
string name = 1;
string age = 2;
string note=3;
}
// 响应消息,包含问候语。
message HelloReply {
string message = 1;
}
Enter at the command line:
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. hello.proto
gRPC client (client.py):
import grpc # 导入gRPC库
import hello_pb2 # 导入生成的proto文件中的消息类型
import hello_pb2_grpc # 导入生成的proto文件中的服务类型
def run():
channel = grpc.insecure_channel('localhost:50051') # 创建与服务器的通信通道,参数为服务器的地址和端口
stub = hello_pb2_grpc.GreeterStub(channel) # 创建与服务器的Stub对象,参数为通信通道
response = stub.SayHello(hello_pb2.HelloRequest(name='John', age='25', note='Hello gRPC')) # 调用服务器上的方法,参数为请求消息对象
print("Response received from server: " + response.message) # 打印服务器返回的响应消息
if __name__ == '__main__':
run() # 运行客户端代码
gRPC server (server.py):
import grpc # 导入gRPC库
from concurrent import futures # 导入concurrent.futures库,用于多线程处理
import hello_pb2 # 导入生成的proto文件中的消息类型
import hello_pb2_grpc # 导入生成的proto文件中的服务类型
class GreeterServicer(hello_pb2_grpc.GreeterServicer):
def SayHello(self, request, context): # 实现proto文件中定义的方法,参数为请求消息对象和上下文对象
message = 'Hello, ' + request.name + '! You are ' + request.age + ' years old.' # 构造响应消息
return hello_pb2.HelloReply(message=message) # 返回响应消息对象
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) # 创建gRPC服务器对象,参数为线程池的最大工作线程数
hello_pb2_grpc.add_GreeterServicer_to_server(GreeterServicer(), server) # 将服务实现添加到服务器中,参数为服务实现对象和服务器对象
server.add_insecure_port('[::]:50051') # 指定服务器监听的地址和端口,参数为地址和端口
server.start() # 启动服务器
print("Server started. Listening on port 50051.") # 打印服务器启动信息
server.wait_for_termination() # 等待服务器终止
if __name__ == '__main__':
serve() # 运行服务器代码
Commonly used protobuf data types and pb files
Commonly used protobuf data types
.proto Type | Notes | C++ Type | Java Type | Python Type[2] | Go Type | Ruby Type |
---|---|---|---|---|---|---|
double | double | double | float | float64 | Float | |
float | float | float | float | float32 | Float | |
int32 | Using variable length encoding is very inefficient for negative values. If your domain may have negative values, please use sint64 instead | int32 | int | int | int32 | Fixnum or Bignum (as needed) |
uint32 | Use variable length encoding | uint32 | int | int | uint32 | Fixnum or Bignum (as needed) |
uint64 | Use variable length encoding | uint64 | long | int | uint64 | Bignum |
sint32 | Use variable-length encodings, which are much more efficient than int32 for negative values | int32 | int | int | int32 | Fixnum or Bignum (as needed) |
sint64 | Signed integer value using variable length encoding. More efficient than usual int64 when encoding. | int64 | long | int | int64 | Bignum |
fixed32 | Always 4 bytes, this type is more efficient than uint32 if the value is always greater than 228. | uint32 | int | int | uint32 | Fixnum or Bignum (as needed) |
fixed64 | Always 8 bytes, this type is more efficient than uint64 if the value is always greater than 256. | uint64 | long | int | uint64 | Bignum |
sfixed32 | always 4 bytes | int32 | int | int | int32 | Fixnum or Bignum (as needed) |
sfixed64 | always 8 bytes | int64 | long | int | int64 | Bignum |
bool | bool | boolean | bool | bool | TrueClass/FalseClass | |
string | A string must be UTF-8 encoded or 7-bit ASCII encoded text. | string | String | str/unicode | string | String (UTF-8) |
bytes | May contain byte data in any order. | string | ByteString | str/b'' | []byte | String (ASCII-8BIT) |
repeated | array(list) | RepeatedField<type> | list | []type | RepeatedField |
map | dictionary | Map<key_type, value_type> | dict | {} | Map |
References: grpc-python02--understand rpc and grpc and create a simple grpc-python_哔哩哔哩_bilibili
gRPC (1) Introduction: What is RPC? | Go Tech Forum
https://www.youtube.com/watch?v=gnchfOojMk4
A simple example of one of the python grpc framework_51CTO Blog_python web framework