Vegeta をライブラリとして利用することで、Goで負荷試験シナリオを柔軟に作ることもできる。
公式ドキュメント
https://github.com/tsenart/vegeta#usage-library
サンプル
package main
import (
"fmt"
"net/http"
"sync/atomic"
"time"
vegeta "github.com/tsenart/vegeta/v12/lib"
)
func main() {
// 負荷試験パラメータ(例: 1秒間に5リクエストを100秒間実行する)
rate := vegeta.Rate{Freq: 5, Per: time.Second}
duration := 100 * time.Second
targets := make([]vegeta.Target, 0)
// リクエストを作る
targets = append(targets, vegeta.Target{
Method: "GET",
URL: "https://example.com/get",
})
targets = append(targets, vegeta.Target{
Method: "POST",
URL: "https://example.com/post",
Body: []byte(`{"name": "Corey", "animal": "dog"}`),
Header: http.Header{
"Content-Type": []string{"application/json"},
},
})
targeter := vegeta.NewStaticTargeter(targets...)
attacker := vegeta.NewAttacker()
var metrics vegeta.Metrics
for res := range attacker.Attack(targeter, rate, duration, "Big Bang!") {
metrics.Add(res)
}
metrics.Close()
fmt.Printf("result: %+v\n", metrics)
}
複雑な例
負荷リクエストのパラメータを可変にしたい場合次のように書ける。
package main
import (
"fmt"
"net/url"
"sync/atomic"
"time"
vegeta "github.com/tsenart/vegeta/v12/lib"
)
func main() {
// 負荷試験パラメータ(例: 1秒間に5リクエストを100秒間実行する)
rate := vegeta.Rate{Freq: 5, Per: time.Second}
duration := 100 * time.Second
targets := make([]vegeta.Target, 0)
// リクエストを作る
targets = append(targets, vegeta.Target{
Method: "GET",
URL: "https://example.com/get?id=00000000",
})
// 自作したTargeterを利用する
targeter := NewCustomTargeter(targets...)
attacker := vegeta.NewAttacker()
var metrics vegeta.Metrics
for res := range attacker.Attack(targeter, rate, duration, "Big Bang!") {
metrics.Add(res)
}
metrics.Close()
fmt.Printf("result: %+v\n", metrics)
}
// NewCustomTargeter targetを作る処理を自作する
func NewCustomTargeter(tgts ...vegeta.Target) vegeta.Targeter {
i := int64(-1)
loopCount := 0
return func(tgt *vegeta.Target) error {
if tgt == nil {
return vegeta.ErrNilTarget
}
addedIndex := atomic.AddInt64(&i, 1)
*tgt = tgts[addedIndex%int64(len(tgts))]
// 1周したらloopCountを増やす
if addedIndex%int64(len(tgts)) == 0 {
loopCount++
}
u, _ := url.Parse(tgt.URL)
q := u.Query()
q.Set("id", fmt.Sprintf("%08d", loopCount))
u.RawQuery = q.Encode()
tgt.URL = u.String()
return nil
}
}