找回密码
 立即注册
查看: 233|回复: 0

Python RPC方法对比:json vs protobuf vs msgpack

[复制链接]
发表于 2022-12-14 17:04 | 显示全部楼层 |阅读模式
背景

远程过程调用有很多技术选型, 例如FastAPI ,gRPC,XML-RPC,msgpack-RPC等。RPC中很重要的一个部分是序列化与反序列化,主流的序列化方法包括xml,json,protobuf和msgpack。本文将基于Python语言对基于不同序列化方法的RPC实现进行简单对比。(注:这些序列化协议都是跨语言的,每个语言都有自己的实现)
设定

考虑一个简单的“加和”服务:服务提供方接受的参数为一个list,需要将list中的数字都加和后,返回加和的结果。
def sum_nums(nums: list[int]) -> int:
    """
    加和传入的nums
    """
    return sum(nums)首先计算纯本地调用(无RPC)的耗时,执行10000次。考虑“低数据量”和“高数据量”两个场景:
低数据量:nums=[1,2]: 1.938ms
高数据量:nums=[1,2,3...,1000]: 52.32msjson-FastAPI

json是使用最为广泛的一种序列化方式,广泛应用于前后端之前的通信,并且有非常好的可读性。基于json的RPC调用,这里选择相对性能较好的FastAPI进行测试。
server端
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()


@app.post("/rpc", status_code=200)
async def rpc(request: Request):
    """
    :param request:
    :return:
    """
    data = await request.json()
    nums = data['nums']
    result = sum_nums(nums)
    return JSONResponse(content={'result': result})通过uvicorn启动服务
uvicorn fast_api_test:app --port 8000client端
nums = list(range(1, 3))
requests.post('http://127.0.0.1:8000/rpc', json={'nums': nums})执行10000次耗时情况
低数据量:nums=[1,2]: 18590.62ms
高数据量:nums=[1,2,3...,1000]: 20385.60msgRPC

protobuf是一种比json性能更高的序列化方式,但是比json的可读性差很多,序列化之后是二进制不可读的。基于protobuf的RPC调用,选择gRPC 进行测试,这也是是后端服务之间广泛采用的一种RPC方式。
首先需要定义一个proto文件
syntax = "proto3";

service RPCTest {
  rpc SumNums(SumNumsRequest) returns (SumNumsResponse) {}
}

message SumNumsRequest {
  repeated int32 nums = 1;
}

message  SumNumsResponse{
  int32 result = 1;
}编译proto文件产生pb2文件和pb2_grpc文件
server端
from concurrent import futures

import test_pb2
import test_pb2_grpc
import grpc


class RPCTest(test_pb2_grpc.RPCTestServicer):
    def SumNums(self, request, context):
        result = sum(request.nums)
        return test_pb2.SumNumsResponse(result=result)


def serve():
    port = '50051'
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=1))
    test_pb2_grpc.add_RPCTestServicer_to_server(RPCTest(), server)
    server.add_insecure_port('[::]:' + port)
    server.start()
    server.wait_for_termination()


if __name__ == '__main__':
    serve()client端
nums = list(range(1, 3))
with grpc.insecure_channel('localhost:50051') as channel:
    stub = test_pb2_grpc.RPCTestStub(channel)
    response = stub.SumNums(test_pb2.SumNumsRequest(nums=nums))执行10000次耗时情况
低数据量:nums=[1,2]: 8654.08ms
高数据量:nums=[1,2,3...,1000]: 10014.39msmsgpack-RPC

msgpack也是一种二进制的传输协议,比json更小也更快,整体性能比protobuf还要更高。同时不需要预先定义proto文件,所以也没有相应的数据校验,这也会让的项目维护成本高很多。


基于msgpack的RPC调用,选择官方的msgpack-rpc进行实验。
server端
import msgpackrpc

class SumServer(object):
    def sum_nums(self, nums: List[int]) -> int:
        return sum(nums)


server = msgpackrpc.Server(SumServer())
server.listen(msgpackrpc.Address("localhost", 18800))
server.start()client端
import msgpackrpc
client = msgpackrpc.Client(msgpackrpc.Address("localhost", 18800))
client.call('sum_nums', nums)执行10000次耗时情况
低数据量:nums=[1,2]: 1111.17ms
高数据量:nums=[1,2,3...,1000]: 1610.63ms整体对比

传输数据无PRCFastAPI (json)gRPC (protobuf)msgpack-rpc
低数据1.938ms18590.62ms8654.08ms1111.17ms
高数据52.32ms20385.60ms10014.39ms1610.63ms



速度对比

可以看到protobuf相比json快了1倍,msgpack相比protobuf快了10倍!
不过protobuf相比json少了可读性,msgpack相比protobuf少了数据校验(协作能力),所以前后端之前的通信一般采用json(为了可读性),后端不同服务的相互协作一般采用protobuf(公共的proto)。如果完全自己维护的不同子服务的通信,可以试试msgpack。
<hr/>持续分享AI算法相关的研究和落地工作,欢迎关注!往期文章汇总:

  • 智能问答系列
nghuyong:基于FAQ的智能问答(一): Elasticsearch的调教
nghuyong:基于FAQ的智能问答(二): 召回篇
nghuyong:基于FAQ的智能问答(三): 精排篇
2. 统计学习方法forNLP系列
nghuyong:统计机器学习方法 for NLP:基于HMM的词性标注
nghuyong:统计机器学习方法 for NLP:基于CRF的词性标注
nghuyong:统计机器学习方法 for NLP:基于LSA的主题模型
nghuyong:统计机器学习方法 for NLP:基于LDA的主题模型
nghuyong:手算KN-based ngram语言模型
3. NLP论文解读
nghuyong:Flan-T5:  One Model for ALL Tasks
nghuyong: 如何评价1700亿参数的GPT-3?
nghuyong: 如何评价OpenAI最新的工作CLIP
4. 其他工程技术
nghuyong:Transformers多机多卡的炼丹实践
nghuyong:文本纠错的论文看这一篇就够了
nghuyong:试试在transformers中调用ERNIE
nghuyong: 如何开始在 github 上学习东西?
nghuyong:Python如何利用多核加速CPU密集型服务

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 15:58 , Processed in 0.090568 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表