# 介绍
# 配置
- 支持配置文件、命令行配置
- 可以指定 proto 源文件或者使用 protoc 生成的 protoset 描述文件
- 支持指定协议名
- 支持导入原始路径列表
- 可以指定秘钥信息
- 可以指定 tls 服务器名称
- 可以跳过 tls
- 是否异步请求,不等待上一个请求完成
- 支持设置 rps
- 支持指定加载进度
- 即可以逐步提高 rps 到预设值
 
- 可以指定并发工作器数量
- 可以指定并发工作器添加策略
- 即逐步增加工作线程
 
- 指定请求总数
- 指定超时时间,默认 20,不限制则设为 0
- 指定持续时间
- 指定停止策略:关闭、等待请求返回、忽略则忽略正在运行的请求
- 指定请求体,以 json 格式
- 指定请求体,以文件形式
- 制定请求体,以二进制形式或者二进制文件
- 指定元数据 ,json 字符串或者文件
- 流式接口的传输测试
- …
- 指定连接数,默认一个连接
- 指定初始连接超时时间
- 可以使用的 cpu 内核数
- 指定客户端负载策略
# 输出
- summary
- csv 格式
- html 格式
- json 格式
- prometheus 格式
- influxDB 格式
# 实践
# 一个 grpc 服务 demo
# pb 编写
syntax = "proto3";  
package pb;  
  
option go_package="./;pb";  
  
message HelloRequest{  
  string name = 1;  
  int32 id = 2;  
}  
  
message HelloReply{  
  string name = 1;  
  string message = 2;  
}  
  
  
service HelloService{  
  rpc Hello(HelloRequest) returns (HelloReply);  
}
# 生成 go 文件和服务端代码
| protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative *.proto | 
# 写一个服务
| package main   | |
| import ( | |
|     "context"   | |
| "fmt" "google.golang.org/grpc" "grpc_demo/pb" "log" "net") | |
| const ( | |
| port = ":50051" | |
| )   | |
| type myServer struct { | |
|     pb.UnimplementedHelloServiceServer   | |
| }   | |
| func (s *myServer) Hello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) { | |
| fmt.Println("hello receice message:", req) | |
| rep := &pb.HelloReply{ | |
| Name: req.Name, | |
| Message: "你好呀", | |
|     }   | |
| return rep, nil | |
| }   | |
| func main() { | |
| lis, err := net.Listen("tcp", port) | |
| if err != nil { | |
| log.Fatalf("failed to listen: %v", err) | |
|     }   | |
|     // 创建一个 gRPC 服务端实例   | |
| s := grpc.NewServer() | |
|     // 注册   | |
| pb.RegisterHelloServiceServer(s, &myServer{}) | |
| if err := s.Serve(lis); err != nil { | |
| log.Fatalf("failed to serve: %v", err) | |
|     }   | |
| } | 
# 压测实践
其中参数解释
- proto 指定原型
- rps 指定目标 rps 值
- total 指定目标请求数
- call 指定要压的方法名
- data 指定请求体数据 json 格式,也可以是数组,那么会轮流请求给定的请求体
- skipTLS insecure 说明使用明文压测
- 最后是服务地址
结果可以看到
- 总结:总请求数、总消耗时间、最慢请求、最快请求、平均时间、QPS
- 响应时间直方图
- 百分比延迟分布
- 响应码分布
| ghz --proto=hello.proto --rps=100 --total=100 --call pb.HelloService.Hello --data='{"name": "xiamu", "id": 1}' --skipTLS --insecure 192.168.31.129:50051 | |
| Summary: | |
|   Count:	100 | |
|   Total:	1.06 s | |
|   Slowest:	497.68 ms | |
|   Fastest:	4.33 ms | |
|   Average:	189.71 ms | |
|   Requests/sec:	94.43 | |
| Response time histogram: | |
| 4.334 [1] |∎∎ | |
| 53.669 [17] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ | |
| 103.004 [19] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ | |
| 152.339 [10] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ | |
| 201.674 [10] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ | |
| 251.008 [10] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ | |
| 300.343 [11] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ | |
| 349.678 [7] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ | |
| 399.013 [5] |∎∎∎∎∎∎∎∎∎∎∎ | |
| 448.348 [5] |∎∎∎∎∎∎∎∎∎∎∎ | |
| 497.683 [5] |∎∎∎∎∎∎∎∎∎∎∎ | |
| Latency distribution: | |
| 10 % in 36.96 ms | |
| 25 % in 67.50 ms | |
| 50 % in 166.24 ms | |
| 75 % in 286.13 ms | |
| 90 % in 397.86 ms | |
| 95 % in 448.03 ms | |
| 99 % in 487.83 ms | |
| Status code distribution: | |
| [OK] 100 responses | |
| ~/code/ghz_test ❯ | 
# 原理
本质上还是 go 协程来实现的。
各个模块区分的很清晰:
- 请求模块
- 数据处理模块
- 日志模块
- 统计模块
- 输出模块
- 连接管理模块
如果用来做自己的压测工具,并且接入 prometheus 监控应该不需要花太大功夫。
此外如果将其改造为 http 的压测,应该也非难事。
# 未来
代码里面还包含一个 ghz 命令,不过还在开发中,可以期待一下。
