1

在当今的软件开发世界中,性能测试和负载测试至关重要。HTTP和gRPC是两种常用的通信协议,许多系统依赖它们进行数据交换和服务调用。然而,选择合适的测试工具来确保这些通信协议的性能和稳定性至关重要。本文将详细探讨使用k6测试HTTP和gRPC的优势,吸引读者从其他测试工具转为使用k6工具。

k6简介

k6 是一个现代化的开源负载和性能测试工具,使用go语言开发。它以其简单易用、功能强大、可扩展性高以及对开发团队友好而著称。k6使用JavaScript作为脚本语言,使得开发人员能够轻松上手,并且与现代开发工具链无缝集成。

k6测试HTTP的优势

  • 简单易用的脚本语言,开发人员可以利用其熟悉的语法和工具链来编写测试脚本。
  • 强大的内置功能,k6内置了丰富的功能和模块,能够满足各种复杂的HTTP测试需求。
  • 高并发和高性能,能够在单一节点上模拟数千个并发用户。
  • 拓展能力和集成,k6与CI/CD工具链、监控系统和分析平台无缝集成,如Jenkins、GitLab、Prometheus和Grafana。这使得性能测试能够更好地嵌入到开发和运维的生命周期中,实现自动化和持续监控。

k6测试gRPC的优势

  • 原生gRPC支持,使得开发人员能够直接在k6脚本中编写和执行gRPC调用。
  • 跨语言和平台支持,轻松测试不同语言实现的gRPC服务。
  • 高性能和低延迟,k6的高效执行引擎能够模拟高强度的gRPC调用场景,验证服务的性能瓶颈和极限。

与其他测试工具的比较

测试工具说明
Apache JMeterApache JMeter是一个历史悠久的性能测试工具,支持多种协议的测试。然而,JMeter的配置和脚本编写相对复杂,学习曲线较陡。与k6相比,JMeter的扩展性和现代集成能力也略显不足。而k6的简单易用性、现代化设计和丰富的扩展能力使其成为更具吸引力的选择。
GatlingGatling是另一个流行的性能测试工具,基于Scala语言。虽然Gatling在高并发测试方面表现出色,但其使用Scala编写脚本对大多数开发人员来说并不友好。此外,Gatling对gRPC的支持相比k6也不够完善。k6的JavaScript脚本和原生gRPC支持使其在易用性和功能性上更具优势。
LocustLocust是一个使用Python编写的负载测试工具,以其简单灵活的脚本编写方式受到欢迎。然而,Locust对高并发的支持不如k6高效,且对gRPC的支持也不如k6原生。另外,k6强大的图表和报告功能也大大增强了测试结果的可视化和可解释性。

k6作为一款现代化的开源负载和性能测试工具,凭借其简单易用的JavaScript脚本语言、强大的内置功能、高并发和高性能表现、以及与现代开发工具链的无缝集成,成为HTTP和gRPC测试的不二选择。通过详细对比其他测试工具,k6在易用性、功能性和扩展性方面展现了显著优势,提升系统的性能测试质量和效率,值得开发团队认真考虑和采用。


测试 kratos、go-zero、sponge 三个微服务框架

主要压测指标

  • 吞吐量(Throughput):单位时间内处理的请求数量,通常以每秒请求数(Requests per Second,RPS)表示。
  • 响应时间(Response Time):从发出请求到收到响应的时间,包括p95、p99、avg、min、max。
  • 错误率(Error Rate):请求处理失败或产生错误的比率。
  • 资源利用率(Resource Utilization):包括cpu、内存、网络带宽等资源的使用情况。


压测api

  • http

    • 端口: 8080
    • 路由: /api/v1/helloworld/qwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnm
    • 请求方法: GET
  • grpc

    • 端口: 8282
    • path: /helloworld.v1.Greeter/SayHello
    • message: qwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnm
    • 类型: unary

注: 8080端口的路由/metrics是采集go程序的指标。


压测工具

  • k6: 用来压测http服务。
  • ghz: 用来压测grpc服务。


压测环境

因为不同的服务器硬件对性能测试结果不一样,本次是在宿主机和虚拟机之间进行负载测试:

  • 宿主机

    • 硬件:R7 6800H CPU,16G内存
    • 用途:运行工具k6和ghz测试http api和grpc api
  • VMware虚拟机

    • 系统:centos 8
    • 硬件:8核cpu、4G内存
    • 用途:用于单独运行kratos、go-zero、sponge创建的http和grpc服务
如果想要在自己的机器上进行负载测试,点击查看压测说明文档


压测结果

50个并发,总共100万个请求,压测kratos、go-zero、sponge创建的http服务结果:

http-server


50个并发,总共100万个请求,压测kratos、go-zero、sponge创建的grpc服务结果:

grpc-server



kratos 创建的服务的压测结果数据

kratos 版本 2.7.2

http 压测结果数据

使用压测工具k6,50个并发,总共100万次请求的结果数据:

$ K6_PROMETHEUS_RW_SERVER_URL="http://192.168.3.37:9090/api/v1/write" K6_PROMETHEUS_RW_TREND_STATS="min,max,avg,p(95),p(99)" K6_PROMETHEUS_RW_PUSH_INTERVAL=1s k6 run -u 50 -i 1000000 -o experimental-prometheus-rw http-load-test.js

  execution: local
     script: http-load-test.js
     output: Prometheus remote write (http://192.168.3.37:9090/api/v1/write)

  scenarios: (100.00%) 1 scenario, 50 max VUs, 10m30s max duration (incl. graceful stop):
           * default: 1000000 iterations shared among 50 VUs (maxDuration: 10m0s, gracefulStop: 30s)

     ✓ status is 200

     checks.........................: 100.00% ✓ 1000000      ✗ 0
     data_received..................: 137 MB  2.3 MB/s
     data_sent......................: 115 MB  2.0 MB/s
     http_req_blocked...............: avg=1.68µs  min=0s med=0s     max=10.12ms p(90)=0s     p(95)=0s
     http_req_connecting............: avg=262ns   min=0s med=0s     max=10.12ms p(90)=0s     p(95)=0s
     http_req_duration..............: avg=2.86ms  min=0s med=2.01ms max=47.44ms p(90)=6.62ms p(95)=8.68ms
       { expected_response:true }...: avg=2.86ms  min=0s med=2.01ms max=47.44ms p(90)=6.62ms p(95)=8.68ms
     http_req_failed................: 0.00%   ✓ 0            ✗ 1000000
     http_req_receiving.............: avg=20.56µs min=0s med=0s     max=4.68ms  p(90)=0s     p(95)=0s
     http_req_sending...............: avg=8.01µs  min=0s med=0s     max=3.77ms  p(90)=0s     p(95)=0s
     http_req_tls_handshaking.......: avg=0s      min=0s med=0s     max=0s      p(90)=0s     p(95)=0s
     http_req_waiting...............: avg=2.83ms  min=0s med=2ms    max=47.44ms p(90)=6.58ms p(95)=8.64ms
     http_reqs......................: 1000000 17085.130811/s
     iteration_duration.............: avg=2.91ms  min=0s med=2.02ms max=47.44ms p(90)=6.68ms p(95)=8.76ms
     iterations.....................: 1000000 17085.130811/s
     vus............................: 50      min=50         max=50
     vus_max........................: 50      min=50         max=50


running (00m58.5s), 00/50 VUs, 1000000 complete and 0 interrupted iterations
default ✓ [======================================] 50 VUs  00m58.5s/10m0s  1000000/1000000 shared iters

压测http api指标的grafana界面:

kratos-http-k6

采集到的服务程序指标的grafana界面:

kratos-http-cpu

kratos-http-go-process


grpc 压测结果数据

使用压测工具ghz,50个并发,总共100万次请求的结果数据。

grpc api压测结果数据:

kratos-grpc-ghz

采集到的服务程序指标的grafana界面:

kratos-grpc-cpu

kratos-grpc-go-process


go-zero 创建的服务的压测结果数据

go-zero 版本 1.6.3

http 压测结果数据

使用压测工具k6,50个并发,总共100万次请求的结果数据:

$ K6_PROMETHEUS_RW_SERVER_URL="http://192.168.3.37:9090/api/v1/write" K6_PROMETHEUS_RW_TREND_STATS="min,max,avg,p(95),p(99)" K6_PROMETHEUS_RW_PUSH_INTERVAL=1s k6 run -u 50 -i 1000000 -o experimental-prometheus-rw http-load-test.js

  execution: local
     script: http-load-test.js
     output: Prometheus remote write (http://192.168.3.37:9090/api/v1/write)

  scenarios: (100.00%) 1 scenario, 50 max VUs, 10m30s max duration (incl. graceful stop):
           * default: 1000000 iterations shared among 50 VUs (maxDuration: 10m0s, gracefulStop: 30s)

     ✓ status is 200

     checks.........................: 100.00% ✓ 1000000      ✗ 0
     data_received..................: 222 MB  3.5 MB/s
     data_sent......................: 115 MB  1.8 MB/s
     http_req_blocked...............: avg=1.67µs  min=0s med=0s     max=8.64ms   p(90)=0s     p(95)=0s
     http_req_connecting............: avg=243ns   min=0s med=0s     max=8.64ms   p(90)=0s     p(95)=0s
     http_req_duration..............: avg=3.08ms  min=0s med=2.05ms max=124.92ms p(90)=6.78ms p(95)=9.13ms
       { expected_response:true }...: avg=3.08ms  min=0s med=2.05ms max=124.92ms p(90)=6.78ms p(95)=9.13ms
     http_req_failed................: 0.00%   ✓ 0            ✗ 1000000
     http_req_receiving.............: avg=21.31µs min=0s med=0s     max=5.89ms   p(90)=0s     p(95)=0s
     http_req_sending...............: avg=8.13µs  min=0s med=0s     max=5.2ms    p(90)=0s     p(95)=0s
     http_req_tls_handshaking.......: avg=0s      min=0s med=0s     max=0s       p(90)=0s     p(95)=0s
     http_req_waiting...............: avg=3.05ms  min=0s med=2.04ms max=124.92ms p(90)=6.75ms p(95)=9.09ms
     http_reqs......................: 1000000 15887.422209/s
     iteration_duration.............: avg=3.13ms  min=0s med=2.08ms max=124.92ms p(90)=6.85ms p(95)=9.21ms
     iterations.....................: 1000000 15887.422209/s
     vus............................: 50      min=50         max=50
     vus_max........................: 50      min=50         max=50


running (01m02.9s), 00/50 VUs, 1000000 complete and 0 interrupted iterations
default ✓ [======================================] 50 VUs  01m02.9s/10m0s  1000000/1000000 shared iters

压测http api指标的grafana界面:

go-zero-http-k6

采集到的服务程序指标的grafana界面:

go-zero-http-cpu

go-zero-http-go-process


grpc 压测结果数据

使用压测工具ghz,50个并发,总共100万次请求的结果数据。

grpc api压测结果数据:

go-zero-grpc-ghz

采集到的服务程序指标的grafana界面:

go-zero-grpc-cpu

go-zero-grpc-go-process


sponge 创建的服务的压测结果数据

sponge 版本 1.7.0

http 压测结果数据

使用压测工具k6,50个并发,总共100万次请求的结果数据:

$ K6_PROMETHEUS_RW_SERVER_URL="http://192.168.3.37:9090/api/v1/write" K6_PROMETHEUS_RW_TREND_STATS="min,max,avg,p(95),p(99)" K6_PROMETHEUS_RW_PUSH_INTERVAL=1s k6 run -u 50 -i 1000000 -o experimental-prometheus-rw http-load-test.js

  execution: local
     script: http-load-test.js
     output: Prometheus remote write (http://192.168.3.37:9090/api/v1/write)

  scenarios: (100.00%) 1 scenario, 50 max VUs, 10m30s max duration (incl. graceful stop):
           * default: 1000000 iterations shared among 50 VUs (maxDuration: 10m0s, gracefulStop: 30s)

     ✓ status is 200

     checks.........................: 100.00% ✓ 1000000      ✗ 0
     data_received..................: 181 MB  3.2 MB/s
     data_sent......................: 115 MB  2.0 MB/s
     http_req_blocked...............: avg=1.75µs  min=0s med=0s     max=10.2ms  p(90)=0s     p(95)=0s
     http_req_connecting............: avg=305ns   min=0s med=0s     max=10.2ms  p(90)=0s     p(95)=0s
     http_req_duration..............: avg=2.74ms  min=0s med=2.04ms max=59.21ms p(90)=5.9ms  p(95)=7.67ms
       { expected_response:true }...: avg=2.74ms  min=0s med=2.04ms max=59.21ms p(90)=5.9ms  p(95)=7.67ms
     http_req_failed................: 0.00%   ✓ 0            ✗ 1000000
     http_req_receiving.............: avg=20.85µs min=0s med=0s     max=8.54ms  p(90)=0s     p(95)=0s
     http_req_sending...............: avg=8.55µs  min=0s med=0s     max=6.16ms  p(90)=0s     p(95)=0s
     http_req_tls_handshaking.......: avg=0s      min=0s med=0s     max=0s      p(90)=0s     p(95)=0s
     http_req_waiting...............: avg=2.72ms  min=0s med=2.02ms max=58.69ms p(90)=5.87ms p(95)=7.63ms
     http_reqs......................: 1000000 17740.077322/s
     iteration_duration.............: avg=2.81ms  min=0s med=2.07ms max=59.21ms p(90)=5.97ms p(95)=7.74ms
     iterations.....................: 1000000 17740.077322/s
     vus............................: 50      min=50         max=50
     vus_max........................: 50      min=50         max=50

running (00m56.4s), 00/50 VUs, 1000000 complete and 0 interrupted iterations
default ✓ [======================================] 50 VUs  00m56.4s/10m0s  1000000/1000000 shared iters

压测http api指标的grafana界面:

sponge-http-k6

采集到的服务程序指标的grafana界面:

sponge-http-cpu

sponge-http-go-process


grpc 压测结果数据

使用压测工具ghz,50个并发,总共100万次请求的结果数据。

grpc api的压测结果数据:

sponge-grpc-ghz

采集到的服务程序指标的grafana界面:

sponge-grpc-cpu

sponge-grpc-go-process


注:上面 kratos、go-zero、sponge 测试http使用的是k6,测试grpc使用压测工具ghz,主要是为了更好的并发性能,这是测试 kratos、go-zero、sponge 完整代码 https://github.com/zhufuyi/microservices_framework_benchmark,可以在这里把ghz改为grpc测试。


gvison
9 声望3 粉丝