1.测试前提,参考先熟悉grpc测试demo:
参考官网:python 实现grpc client以及service :
https://grpc.io/docs/quickstart/python/
java实现client 和service:https://grpc.io/docs/quickstart/java/
细节我就不讲了:
主要说下.proto文件,他是实现grpc的基础,根据他产生契约helloworld_pb2,以及客户端服务端调用类:helloworld_pb2_grpc(核心调用client编写就靠他的Stub 类):
生成契约和grpc client和 service 类
$ python -m grpc_tools.protoc -I ../../protos --python_out=. --grpc_python_out=. ../../protos/helloworld.proto
依赖文件:
grpcio==1.28.1 grpcio-tools==1.28.1 protobuf==3.11.3 coverage>=4.0 cython>=0.29.8 enum34>=1.0.4 #protobuf>=3.5.0.post1 six>=1.10 wheel>=0.29
setuptools==46.1.3
2.linux 环境搭建安装python3:
虚拟环境:基于virtualenv
安装依赖
3.安装ghz工具,安装go:
ghza安装包下载:https://github.com/bojand/ghz/releases
wget https://github.com/bojand/ghz/releases/download/v0.52.0/ghz_0.52.0_Linux_x86_64.tar.gz
ghz 帮助文档:https://ghz.sh/docs/options
配置ghz和go环境变量vi/etc/profile:
export PATH=$PATH:/usr/local/go/bin export PATH=$PATH:/project
source /etc/profile:
验证golang ,ghz 环境:
go version
ghz -h
4.启动grpc server:
编写一个简单的服务端grpc_server和对应的client 先mock下server可用,然后进行ghz工具压测server :
[root@vm_master helloword]# cat grpc_client.py import logging import time import grpc import helloworld_pb2 import helloworld_pb2_grpc import json def run(): with grpc.insecure_channel(‘localhost:50051‘) as channel: stub = helloworld_pb2_grpc.GreeterStub(channel) req={"name":"jack","id":1001}
# transfer json object to bytes to send grpc request body=json.dumps(req).encode("utf-8") response = stub.SayHello(helloworld_pb2.HelloRequest(name=body)) # print(type(response.message)) print(response.message) if __name__ == ‘__main__‘: logging.basicConfig() run()
grpc_server.py:
from concurrent import futures import logging import grpc import helloworld_pb2 import helloworld_pb2_grpc class Greeter(helloworld_pb2_grpc.GreeterServicer): def SayHello(self, request, context): return helloworld_pb2.HelloReply(message= 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() server.wait_for_termination() if __name__ == ‘__main__‘: logging.basicConfig() serve()
启动服务端 python grpc_server.py,在运行client测试,查看结果:
C:\Python37\python.exe D:/workspace/demos/python/helloword/grpc_client.py
{"name": "jack", "id": 1001}
Process finished with exit code 0
,接着进行压测:
前面已经安装好了ghz ,接着进行压力测试:
鉴于ghz 命令基于linux所以打算借助脚本调用 ghz 压力测试命令,以及请求参数构造:
脚本:
import subprocess import json def exe_cmd(args): sub=subprocess.Popen(args,shell=False,stdout=subprocess.PIPE,stderr=subprocess.STDOUT) out,err=sub.communicate() return out.decode("utf-8") def demo(): bytes_data={"name":"zhangsan","id":"10001"} bytes_data=json.dumps(bytes_data).encode("utf-8") args=["ghz","--skipTLS","--insecure","--proto","../../protos/helloworld.proto", "--call","helloworld.Greeter.SayHello","--metadata",bytes_data,"-c","5","--qps","100","-z","1m","--connections","5","-t","20s","0.0.0.0:50051"] print(exe_cmd(args)) if __name__ == ‘__main__‘: demo()
这里输出默认是命令行展示结果:
[root@vm_master helloword]# python deso.py
Summary:
Count: 29761
Total: 60.01 s
Slowest: 71.66 ms
Fastest: 0.52 ms
Average: 3.63 ms
Requests/sec: 495.95
Response time histogram:
0.515 [1] |
7.630 [29219] |????????????????????????????????????????
14.744 [384] |?
21.859 [133] |
28.973 [8] |
36.088 [2] |
43.202 [0] |
50.317 [3] |
57.431 [2] |
64.546 [4] |
71.660 [1] |
Latency distribution:
10 % in 1.67 ms
25 % in 2.03 ms
50 % in 3.36 ms
75 % in 4.82 ms
90 % in 5.76 ms
95 % in 6.37 ms
99 % in 12.27 ms
Status code distribution:
[OK] 29757 responses
[Unavailable] 2 responses
[Canceled] 2 responses
Error distribution:
[2] rpc error: code = Unavailable desc = transport is closing
[2] rpc error: code = Canceled desc = grpc: the client connection is closing
为了方便阅读,可以保存为html 只需添加参数 -o ./result.html -O html既可
args=["ghz","--skipTLS","--insecure","--proto","../../protos/helloworld.proto",
"--call","helloworld.Greeter.SayHello","--metadata",bytes_data,"-o","./result.html","-O","html","-c","5","-n","10","0.0.0.0:50051"]
html参考效果:https://ghz.sh/sample.html
output指标解释:https://ghz.sh/docs/output
注意事项:
def demo():
bytes_data={"name":"zhangsan","id":"10001"}
bytes_data=json.dumps(bytes_data).encode("utf-8")
args=["ghz","--skipTLS","--insecure","--proto","../../protos/helloworld.proto",
"--call","helloworld.Greeter.SayHello","--metadata",bytes_data,"-c","5","--qps","100","-z","1m","--connections","5","-t","20s","0.0.0.0:50051"]
print(exe_cmd(args))
这里bytes_data=里整数按字符串填写,否则go 转换出错,其次 一般 -d {"key":"value"}需要在proto文件定义type,这里为了通用传输字节,我直接按metadata元数据传输他会自动处理