123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- package main
- import (
- "flag"
- "fmt"
- "net/http"
- "os"
- "sync"
- "time"
- "github.com/tal-tech/go-zero/core/lang"
- "github.com/tal-tech/go-zero/core/logx"
- "github.com/tal-tech/go-zero/core/threading"
- "gopkg.in/cheggaaa/pb.v1"
- )
- var (
- freq = flag.Int("freq", 100, "frequency")
- duration = flag.String("duration", "10s", "duration")
- )
- type (
- counting struct {
- ok int
- fail int
- reject int
- errs int
- unknown int
- }
- metric struct {
- counting
- lock sync.Mutex
- }
- )
- func (m *metric) addOk() {
- m.lock.Lock()
- m.ok++
- m.lock.Unlock()
- }
- func (m *metric) addFail() {
- m.lock.Lock()
- m.ok++
- m.lock.Unlock()
- }
- func (m *metric) addReject() {
- m.lock.Lock()
- m.ok++
- m.lock.Unlock()
- }
- func (m *metric) addErrs() {
- m.lock.Lock()
- m.errs++
- m.lock.Unlock()
- }
- func (m *metric) addUnknown() {
- m.lock.Lock()
- m.unknown++
- m.lock.Unlock()
- }
- func (m *metric) reset() counting {
- m.lock.Lock()
- result := counting{
- ok: m.ok,
- fail: m.fail,
- reject: m.reject,
- errs: m.errs,
- unknown: m.unknown,
- }
- m.ok = 0
- m.fail = 0
- m.reject = 0
- m.errs = 0
- m.unknown = 0
- m.lock.Unlock()
- return result
- }
- func runRequests(url string, frequency int, metrics *metric, done <-chan lang.PlaceholderType) {
- ticker := time.NewTicker(time.Second / time.Duration(frequency))
- defer ticker.Stop()
- for {
- select {
- case <-ticker.C:
- go func() {
- resp, err := http.Get(url)
- if err != nil {
- metrics.addErrs()
- return
- }
- defer resp.Body.Close()
- switch resp.StatusCode {
- case http.StatusOK:
- metrics.addOk()
- case http.StatusInternalServerError:
- metrics.addFail()
- case http.StatusServiceUnavailable:
- metrics.addReject()
- default:
- metrics.addUnknown()
- }
- }()
- case <-done:
- return
- }
- }
- }
- func main() {
- flag.Parse()
- fp, err := os.Create("result.csv")
- logx.Must(err)
- defer fp.Close()
- fmt.Fprintln(fp, "seconds,goodOk,goodFail,goodReject,goodErrs,goodUnknowns,goodDropRatio,"+
- "heavyOk,heavyFail,heavyReject,heavyErrs,heavyUnknowns,heavyDropRatio")
- var gm, hm metric
- dur, err := time.ParseDuration(*duration)
- logx.Must(err)
- done := make(chan lang.PlaceholderType)
- group := threading.NewRoutineGroup()
- group.RunSafe(func() {
- runRequests("http://localhost:8080/heavy", *freq, &hm, done)
- })
- group.RunSafe(func() {
- runRequests("http://localhost:8080/good", *freq, &gm, done)
- })
- go func() {
- ticker := time.NewTicker(time.Second)
- defer ticker.Stop()
- var seconds int
- for range ticker.C {
- seconds++
- g := gm.reset()
- h := hm.reset()
- fmt.Fprintf(fp, "%d,%d,%d,%d,%d,%d,%.1f,%d,%d,%d,%d,%d,%.1f\n",
- seconds, g.ok, g.fail, g.reject, g.errs, g.unknown,
- float32(g.reject)/float32(g.ok+g.fail+g.reject+g.unknown),
- h.ok, h.fail, h.reject, h.errs, h.unknown,
- float32(h.reject)/float32(h.ok+h.fail+h.reject+h.unknown))
- }
- }()
- go func() {
- bar := pb.New(int(dur / time.Second)).Start()
- ticker := time.NewTicker(time.Second)
- defer ticker.Stop()
- for range ticker.C {
- bar.Increment()
- }
- bar.Finish()
- }()
- <-time.After(dur)
- close(done)
- group.Wait()
- time.Sleep(time.Millisecond * 900)
- }
|