Awesome
Trunks
Trunks, like every son, is derived from the father Vegeta with some enhanced skills:
- dump HTTP reponses
- gRPC support
Current Tag v13.0.0
Usage manual
for original usage of Vegeta, please refer to vegeta' readme
More functionalities
dump http attck response to file
(add one more option '-respf' to 'attack')
-respf string
Dump responses to file
gRPC perf test (as lib)
Trunks uses the burn to attack the gRPC services. Capable with any gRPC service.
Given multiple hosts ('IP:port' of service instances), Trunks will use simple round-robin as client-side load balance mechanism.
Burning duration is shorter. No need to do the real service discovery or watch / real-time live connection's update. Say, if testing service instances registered to Etcd, we don't need to watch the status of all instances and adjust the connection pool. During the short time of perf testing, we assume the instance hosts are not-changing.
Example:
This example is using "google.golang.org/grpc/examples/route_guide" as the target server.
package main
import (
"fmt"
"time"
trunks "github.com/straightdave/trunks/lib"
// for convenience, change the client_stub.pb.go into package main
)
func main() {
tgt := &trunks.Gtarget{
MethodName: "/routeguide.RouteGuide/GetFeature",
Requests: []proto.Message{&Point{Latitude: 10000, Longitude: 10000}}, // supporting multiple requests
Response: &Feature{}, // providing one response data struct
}
burner, err := trunks.NewBurner(
[]string{"192.168.0.1:8087"}, // server address pool; simple round-robin
trunks.WithLooping(true), // loop requests; false by default
trunks.WithNumWorker(20), // worker goroutine pool size; 10 is default
trunks.WithDumpFile("a.dump"), // dump responses to file
)
if err != nil {
fmt.Println(err)
return
}
defer burner.Close()
var metrics trunks.Metrics
startT := time.Now()
// burning the target service with QPS=5 and Duration=10s
for res := range burner.Burn(tgt, uint64(5), 10*time.Second) {
metrics.Add(res)
}
dur := time.Since(startT)
metrics.Close()
fmt.Printf("dur: %v\n", dur.Seconds())
fmt.Printf("earliest: %v\n", metrics.Earliest.Sub(startT).Nanoseconds())
fmt.Printf("latest: %v\n", metrics.Latest.Sub(startT).Nanoseconds())
fmt.Printf("end: %v\n", metrics.End.Sub(startT).Nanoseconds())
fmt.Printf("reqs: %d\n", metrics.Requests)
fmt.Printf("success%: %f\n", metrics.Success)
fmt.Printf("p50: %s\n", metrics.Latencies.P50)
fmt.Printf("p95: %s\n", metrics.Latencies.P95)
fmt.Printf("p99: %s\n", metrics.Latencies.P99)
fmt.Printf("mean: %s\n", metrics.Latencies.Mean)
fmt.Printf("max: %s\n", metrics.Latencies.Max)
// ...
}
For this code snippet, it would result in:
dur: 9.802099215
earliest: 68670
latest: 9800068577
end: 9802058490
reqs: 50
success%: 99.88
p50: 5.974748ms
p95: 6.084433ms
p99: 6.10946ms
mean: 5.143272ms
max: 6.19225ms
Arion as gRPC
Arion makes it easy to use Trunks. Please check https://github.com/straightdave/arion