编写一个接口压测工具-编程思维

前言

前段时间有个项目即将上线,需要对其中的核心接口进行压测;由于我们的接口是 gRPC 协议,找了一圈发现压测工具并不像 HTTP 那么多。

最终发现了 ghz 这个工具,功能也非常齐全。

事后我在想为啥做 gRPC 压测的工具这么少,是有什么难点嘛?为了验证这个问题于是我准备自己写一个工具。

特性

前前后后大概花了个周末的时间完成了相关功能。

https://github.com/crossoverJie/ptg/

也是一个命令行工具,使用起来效果如上图;完整的命令如下:

NAME:
   ptg - Performance testing tool (Go)

USAGE:
   ptg [global options] command [command options] [arguments...]

COMMANDS:
   help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --thread value, -t value              -t 10 (default: 1 thread)
   --Request value, --proto value        -proto http/grpc (default: http)
   --protocol value, --pf value          -pf /file/order.proto
   --fully-qualified value, --fqn value  -fqn package.Service.Method
   --duration value, -d value            -d 10s (default: Duration of test in seconds, Default 10s)
   --request value, -c value             -c 100 (default: 100)
   --HTTP value, -M value                -m GET (default: GET)
   --bodyPath value, --body value        -body bodyPath.json
   --header value, -H value              HTTP header to add to request, e.g. "-H Content-Type: application/json"
   --target value, --tg value            http://gobyexample.com/grpc:127.0.0.1:5000
   --help, -h                            show help (default: false)

考虑到受众,所以同时支持 HTTPgRPC 接口的压测。

gRPC 压测时所需的参数要多一些:

ptg -t 10 -c 100 -proto grpc  -pf /xx/xx.proto -fqn hello.Hi.Say -body test.json  -tg "127.0.0.1:5000"

比如需要提供 proto 文件的路径、具体的请求参数还有请求接口的全路径名称。

目前只支持最常见的 unary call 调用,后续如果有需要的话也可以 stream。

同时也支持压测时间、次数两种压测方式。

安装

想体验度朋友如果本地有 go 环境那直接运行:

go get github.com/crossoverJie/ptg

没有环境也没关系,可以再 release 页面下载与自己环境对应的版本解压使用。


https://github.com/crossoverJie/ptg/releases

设计模式

整个开发过程中还是有几个点想和大家分享,首先是设计模式。

因为一开始设计时就考虑到需要支持不同的压测模式(次数、时间;后续也可以新增其他的模式)。

所以我便根据压测的生命周期定义了一套接口:

type (
	Model interface {
		Init()
		Run()
		Finish()
		PrintSate()
		Shutdown()
	}
)	

从名字也能看出来,分别对应:

  • 压测初始化
  • 运行压测
  • 停止压测
  • 打印压测信息
  • 关闭程序、释放资源


然后在两个不同的模式中进行实现。

这其实就是一个典型的依赖倒置原则。

程序员要依赖于抽象接口编程、不要依赖具体的实现。

其实大白话就是咱们 Java 里常说的面向接口编程;这个编程技巧在开发框架、SDK或是多种实现的业务中常用。

好处当然是显而易见:
当接口定义好之后,不同的业务只需要根据接口实现自己的业务就好,完全不会互相影响;维护、扩展都很方便。

支持 HTTPgRPC 也是同理实现的:

type (
	Client interface {
		Request() (*Response, error)
	}
)	


当然前提得是前期的接口定义需要考虑周全、不能之后频繁修改接口定义,这样的接口就没有意义了。

goroutine

另外一点则是不得不感叹 goroutine+select+channel 这套并发编程模型真的好用,并且也非常容易理解。

很容易就能写出一套并发代码:

func (c *CountModel) Init() {
	c.wait.Add(c.count)
	c.workCh = make(chan *Job, c.count)
	for i := 0; i < c.count; i++ {
		go func() {
			c.workCh <- &Job{
				thread:   thread,
				duration: duration,
				count:    c.count,
				target:   target,
			}
		}()
	}
}

比如这里需要初始化 N 个 goroutine 执行任务,只需要使用 go 关键字,然后利用 channel 将任务写入。

当然在使用 goroutine+channel 配合使用时也得小心 goroutine 泄露的问题;简单来说就是在程序员退出时还有 goroutine 没有退出。

比较常见的例子就是向一个无缓冲的 channel 中写数据,当没有其他 goroutine 来读取数时,写入的 goroutine 就会被一直阻塞,最终导致泄露。

总结

gRPC 接口压测需求的朋友欢迎试用,提出宝贵意见;当然 HTTP 接口也可以。

源码地址:
https://github.com/crossoverJie/ptg/

版权声明:本文版权归作者所有,遵循 CC 4.0 BY-SA 许可协议, 转载请注明原文链接
https://www.cnblogs.com/crossoverJie/p/15557448.html

(转)Python——gRPC详解及实战避坑方案(上)-编程思维

原文:https://juejin.cn/post/6854573212018147336 前言 什么是RPC服务 RPC,是Remote Procedure Call的简称,翻译成中文就是远程过程调用。RPC就是允许程序调用另一个地址空间(通常是另一台机器上)的类方法或函数的一种服务。 它是一种架设在计算机网络之

Consul 入门-gRPC 服务注册与发现-编程思维

前言 假如我有钱,我想买一个降噪耳机,我应该哪里买? 答案很简单,可以去京东或者线下实体店。 那如果把这个问题映射到微服务架构中:我打开京东,选中某款耳机进入详情页浏览,我可以看到这款耳机的价格、库存、规格、评价等。以我的理解,这个链路应该是这样的: 暂定这个系统由3个微服务组成:商品详情服务、库存服务、评价服务。 商

撸了一个可调试 gRPC 的 GUI 客户端-编程思维

前言 平时大家写完 gRPC 接口后是如何测试的?往往有以下几个方法: 写单测代码,自己模拟客户端测试。 可以搭一个 gRPC-Gateway 服务,这样就可以在 postman 中进行模拟。 但这两种方法都不是特别优雅;第一种方法当请求结构体嵌套特别复杂时,在代码中维护起来就不是很直观;而且代码会特别长。 第

【.NET6】gRPC服务端和客户端开发案例,以及minimal API服务、gRPC服务和传统webapi服务的访问效率大对决-编程思维

 前言:随着.Net6的发布,Minimal API成了当下受人追捧的角儿。而这之前,程序之间通信效率的王者也许可以算得上是gRPC了。那么以下咱们先通过开发一个gRPC服务的教程,然后顺势而为,再接着比拼一下minimal api服务和gRPC服务在通信上的效率。以下,Enjoy: 1、创建一个gRPC服务项目。开发

计算机基础-HTTP-编程思维

计算机基础-HTTP       笑渐不闻声渐悄,多情却被无情恼。   简介:计算机基础-HTTP。 一 、基础概念 请求和响应报文 客户端发送一个请求报文给服务器,服务器根据请求报文中的信息进行处理,并将处理结果放入响应报文中返回给客户端。 请求报文结构: 第一行是包含了请求方法、URL、协议版本; 接下来的多行都是

实现 API 调用接口-编程思维

实现 API 调用接口 API 简介 API 的概念 API(Application Programming Interface) 应用程序编程接口是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一次例程的能力,而又无需访问源码或理解内部工作机制的细节。 API 的特点 一个明确定义的接口,可

手机端上传照片实现 压缩、拖放、缩放、裁剪、合成拼图等功能-编程思维

一、序   如题,最近工作中遇到一个移动端用户上传照片,然后在线编辑,添加一些别的图片合成的功能,类似于超级简化版美图秀秀。总结了一下,大致操作包含 上传图片,图片压缩、触摸拖动图片、放大/缩小、添加别的图片进行合成,最后生成一张新图片。功能比较多,问遍了度娘,也没什么系统的有用信息。蛋疼。。。于是挽起袖子自己撸代码。

node.js 递归复制文件夹(附带文件过滤功能)-编程思维

 1、简介:   很简单,写了一个node操作文件的小脚本,主要实现对目标文件夹中内容的复制。还顺带一个按照文件夹或者文件名过滤的功能。 2、应用场景   适合基于 node 环境的项目,项目打包的时候,配合 webpack 配置,生成需要的线上项目目录,方便快捷。 3、 使用说明   代码我检验过,应该是没bug的

go 自定义http.Client - 动态修改请求Body-编程思维

前言 在对接Alexa Smart Home时,有的请求Payload中需要传入Access Token,但是这个Token是由OAuth2 Client管理的,封装Payload时并不知道Access Token。 所以使用自定义RoundTripper,在请求前取出Header里的token,修改body,实现动态