Preface
Some time ago, a project was about to go online, and the core interface needs to be pressure tested; because our interface is the gRPC
protocol, I found that there are not as many HTTP
Finally, I found the ghz , which is also very versatile.
Afterwards, I was wondering why gRPC
stress testing. Is there any difficulty? In order to verify this problem, I am going to write a tool myself.
<!--more-->
characteristic
It probably took a weekend to complete the related functions.
https://github.com/crossoverJie/ptg/
It is also a command line tool, the effect is as shown above; the complete command is as follows:
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)
Considering the audience, it supports the pressure test of the HTTP
and gRPC
gRPC
are more parameters required for 06191aa1bc5fb0 pressure test:
ptg -t 10 -c 100 -proto grpc -pf /xx/xx.proto -fqn hello.Hi.Say -body test.json -tg "127.0.0.1:5000"
For example, you need to provide proto
file, the specific request parameters, and the full path name of the request interface.
Currently, only the most common unary call is supported, and it can be streamed later if necessary.
At the same time, it also supports two pressure measurement methods: time and frequency.
Install
If you want to experience friends, if you have a go environment locally, run it directly:
go get github.com/crossoverJie/ptg
It doesn't matter if there is no environment, you can download the version corresponding to your environment from the release page and decompress it for use.
https://github.com/crossoverJie/ptg/releases
Design Patterns
There are still a few points to share with you throughout the development process, the first is the design pattern.
Because at the beginning of the design, it is considered to support different pressure test modes (number of times, time; other modes can be added later).
So I defined a set of interfaces based on the life cycle of stress testing:
type (
Model interface {
Init()
Run()
Finish()
PrintSate()
Shutdown()
}
)
It can also be seen from the name, respectively corresponding to:
- Stress test initialization
- Run pressure test
- Stop pressure test
- Print pressure test information
- Close the program and release resources
Then implement it in two different modes.
This is actually a typical dependency inversion principle.
Programmers must rely on abstract interface programming, not on specific implementations.
In fact, the vernacular is the Java
; this programming technique is commonly used in development frameworks, SDKs, or multiple implementations of business.
The benefits are of course obvious:
After the interface is defined, different businesses only need to implement their own business based on the interface, and will not affect each other at all; maintenance and expansion are very convenient.
Support for HTTP
and gRPC
is also achieved in the same way:
type (
Client interface {
Request() (*Response, error)
}
)
Of course, the premise is that the interface definition in the early stage needs to be considered thoroughly, and the interface definition cannot be frequently modified later, so the interface is meaningless.
goroutine
Another point is that I have to sigh that the goroutine+select+channel
really easy to use and easy to understand.
It is easy to write a set of concurrent code:
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,
}
}()
}
}
For example, here you need to initialize N goroutine
perform tasks, you only need to use the go
keyword, and then use the channel to write the task.
Of course, when using goroutine+channel
conjunction with the use, you must also be careful goroutine
leakage of 06191aa1bc64c7; in simple terms, there is still goroutine
does not exit when the programmer exits.
A more common example is to channel
. When there is no other goroutine
to read the data, the written goroutine
will eventually lead to leakage.
Summarize
Friends with gRPC
interface pressure test requirements are welcome to try it and provide valuable comments; of course, the HTTP
interface is also available.
Source address:
https://github.com/crossoverJie/ptg/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。