【k6】gRPC服务性能测试
- 🎉 v0.29.0的新功能
- 什么是gRPC?
- API类型
- 一元
- 流媒体服务器
- 流媒体客户端
- 双向流
- proto定义
- 引言
- 创建测试
- 运行测试
- 摘要
- 参阅
* Simon Aronsson(开发者推广大使)著,Ng Wai Foong 译
🎉 v0.29.0的新功能
v0.29.0包含许多特别有用的功能。 查看发布版本通知以了解更多详细信息!
什么是gRPC?
gRPC是一个轻量级的开源的RPC框架,它最初是由谷歌(Google)开发的,2016年8月发布了1.0版本。此后,它得到了广泛的关注和采用。
与作为人类可读的文本传输的JSON相比,gRPC是二进制的,使其传输速度更快,而且它的结构更紧凑。在我们看到的基准测试中,事实证明gRPC比传统的基于JSON的REST快得多。
按照Auth0的基准,性能高达6倍,而其他基准,如Alex Pliutau的基准和Ruwan Fernando的基准,则显示出高达10倍的改进。
对于分布式系统和涉及客户端与服务器之间大量通信的系统,这些改进意义重大,差异不仅在基准上明显,而且从终端用户的角度来看也非常明显
API类型
gRPC支持四种不同类型的RPC,一元(unary)、流媒体服务器(server streaming)、流媒体客户端(client streaming)和双向流(bi-directional streaming)。实际上,消息是使用相同的连接进行复用的,为了简单起见,下面的gRPC服务模型图中并未说明这个概念。
一元
一元的方式与常规函数调用相同,客户向服务器发送一个请求,服务器回复一个响应。
流媒体服务器
在流媒体服务器模式下,客户向服务器发送一个请求,服务器回复多个响应。
流媒体客户端
流媒体客户端模式与流媒体服务器模式相反,客户向服务器发送多个请求,服务器回复一个响应。
双向流
在双向流模式下,客户或服务器是可以互相发送多个信息。
proto定义
.proto文件中描述了gRPC相关的消息和服务,包含了Protocol buffers或protobuf和它的定义。然后,定义文件被用来生成可被发送方和接收方使用的代码,作为通过这些信息和服务进行交流的合同,由于gRPC使用的二进制格式缺乏自描述属性,所以需要这个文件来解释消息。
在本文中,我们将使用hello.proto
定义,您可以通过k6的grpcbin网页下载它,有关如何构建自己的gRPC proto定义的详细信息,请参考官方gRPC文档.
// ./definitions/hello.proto
// based on https://grpc.io/docs/guides/concepts.html
syntax = "proto2";
package hello;
service HelloService {
rpc SayHello(HelloRequest) returns (HelloResponse);
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
}
message HelloRequest {
optional string greeting = 1;
}
message HelloResponse {
required string reply = 1;
}
引言
在k6 v0.29.0中,我们很高兴为gRPC通信引入一个原生客户端,在此版本中,我们为一元模式提供了良好的支持,如果其他模式对您有用,我们想进一步了解您的用例,这样以来我们可以为您优先考虑这些功能。
目前k6中使用原生客户端的gRPC API如下所示:
函数 | 说明 |
Client.load(importPaths, …protoFiles) | 为gRPC请求加载并解析给定的协议缓冲区定义。 |
Client.connect(address [,params]) | 打开与gRPC服务器的连接 |
Client.invoke(url, request [,params]) | 对服务进行一元RPC并返回响应。 |
Client.close() | 关闭与gRPC服务的连接。 |
创建测试
gRPC模块是一个单独的包,可以从您的测试脚本中以k6/net/grpc
的形式调用,在调用之前,我们必须创建一个客户端的实例,客户端实例化和.load
操作仅在测试初始化时才能使用,例如直接在global范围内。
import grpc from 'k6/net/grpc';
const client = new grpc.Client();
接下来,我们将为要测系统加载一个.proto
定义。在本文中,我们将使用k6 grpcbin,您可以使用自己的请求和响应服务,但请记住:“在测试时提供相应的.proto
定义,.load()
函数接收两个参数,第一个是proto文件路径数组,第二个是要加载的文件名。”
import grpc from 'k6/net/grpc';
const client = new grpc.Client();
client.load(['definitions'], 'hello.proto');
完成后,我们将继续写我们的测试脚本。
import grpc from 'k6/net/grpc';
const client = new grpc.Client();
client.load(['definitions'], 'hello.proto');
export default () => {
client.connect('grpcbin.test.k6.io:9001', {
// plaintext: false
});
const data = { greeting: 'Bert' };
const response = client.invoke('hello.HelloService/SayHello', data);
check(response, {
'status is OK': (r) => r && r.status === grpc.StatusOK,
});
console.log(JSON.stringify(response.message));
client.close();
sleep(1);
};
接下来,我们看一下以上的脚本以了解更多,我们首先调用.connect()
函数连接到我们的测试系统,默认情况下,客户端会将plaintext
参数设置为false
,仅允许您使用加密的连接,如果您想连接到一个没有SSL/TLS的服务器,您只需将参数更改为true
。
继续创建要发送到grpc服务器的对象,至于SayHello
,我们可以用greeting
参数指定greeting地址。
接下来,我们使用proto文件中所述的语法<package>.<service>/<procedure>
调用远程过程,该调用是同步进行的,默认超时时间为60000 ms(60秒),你可以通过在.connect()
的config对象中加入timeout
来改变超时时间,例如'2s'
为2秒。
一旦我们收到服务器的响应,就意味着程序执行成功,k6的grpc模块包含了用于这种比较的常量,在此处列出。
响应状态grpc.StatusOK
相当于HTTP/1.1中的200 OK
,使用它进行比较可确保调用成功完成。
然后,我们将记录响应消息,关闭客户端连接并进行sleep
一秒钟。
运行测试
这个测试可以像其他测试一样运行,但你需要至少v0.29.0
版本才能运行gRPC模块,运行以下命令以检查k6版本。
$ k6 version
k6 v0.29.0 ((devel), go1.15.3, darwin/amd64)
如果版本低于v0.29.0
,请更新k6,您可以在此处找到安装说明。
完成后,继续运行我们的测试:
$ k6 run test.js
/\ |‾‾| /‾‾/ /‾‾/
/\ / \ | |/ / / /
/ \/ \ | ( / ‾‾\
/ \ | |\ \ | (‾) |
/ __________ \ |__| \__\ \_____/ .io
execution: local
script: /Users/simme/code/grpc/test.js
output: -
scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
* default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)
INFO[0000] {"reply":"hello Bert"} source=console
running (00m01.4s), 0/1 VUs, 1 complete and 0 interrupted iterations
default ✓ [======================================] 1 VUs 00m01.4s/10m0s 1/1 iters, 1 per VU
✓ status is OK
checks...............: 100.00% ✓ 1 ✗ 0
data_received........: 3.0 kB 2.1 kB/s
data_sent............: 731 B 522 B/s
grpc_req_duration....: avg=48.44ms min=48.44ms med=48.44ms max=48.44ms p(90)=48.44ms p(95)=48.44ms
iteration_duration...: avg=1.37s min=1.37s med=1.37s max=1.37s p(90)=1.37s p(95)=1.37s
iterations...........: 1 0.714536/s
vus..................: 1 min=1 max=1
vus_max..............: 1 min=1 max=1
从输出结果来看,我们的脚本运行正常,服务器的响应为{"reply":"hello Bert"}
,Bert
是我们在请求中发送的参数,我们也可以看到,check
成功了,也就是说服务器响应了200 OK
。
摘要
在本文中,我们介绍了gRPC的一些基本原理以及如何使用它,我们还了解了k6 v0.29.0版本中引入的gRPC客户端。然后,我们创建了一个
测试脚本来展示这个功能。
本篇gRPC负载测试教程就到此结束了。感谢您的阅读!
参阅