stresser.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "net"
  6. "net/http"
  7. "sync"
  8. "time"
  9. "github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context"
  10. "github.com/coreos/etcd/client"
  11. )
  12. type Stresser interface {
  13. // Stress starts to stress the etcd cluster
  14. Stress() error
  15. // Cancel cancels the stress test on the etcd cluster
  16. Cancel()
  17. // Report reports the success and failure of the stress test
  18. Report() (success int, failure int)
  19. }
  20. type stresser struct {
  21. Endpoint string
  22. KeySize int
  23. KeySuffixRange int
  24. N int
  25. // TODO: not implemented
  26. Interval time.Duration
  27. mu sync.Mutex
  28. failure int
  29. success int
  30. cancel func()
  31. }
  32. func (s *stresser) Stress() error {
  33. cfg := client.Config{
  34. Endpoints: []string{s.Endpoint},
  35. Transport: &http.Transport{
  36. Dial: (&net.Dialer{
  37. Timeout: time.Second,
  38. KeepAlive: 30 * time.Second,
  39. }).Dial,
  40. MaxIdleConnsPerHost: s.N,
  41. },
  42. }
  43. c, err := client.New(cfg)
  44. if err != nil {
  45. return err
  46. }
  47. kv := client.NewKeysAPI(c)
  48. ctx, cancel := context.WithCancel(context.Background())
  49. s.cancel = cancel
  50. for i := 0; i < s.N; i++ {
  51. go func() {
  52. for {
  53. setctx, setcancel := context.WithTimeout(ctx, time.Second)
  54. key := fmt.Sprintf("foo%d", rand.Intn(s.KeySuffixRange))
  55. _, err := kv.Set(setctx, key, randStr(s.KeySize), nil)
  56. setcancel()
  57. if err == context.Canceled {
  58. return
  59. }
  60. s.mu.Lock()
  61. if err != nil {
  62. s.failure++
  63. } else {
  64. s.success++
  65. }
  66. s.mu.Unlock()
  67. }
  68. }()
  69. }
  70. <-ctx.Done()
  71. return nil
  72. }
  73. func (s *stresser) Cancel() {
  74. s.cancel()
  75. }
  76. func (s *stresser) Report() (success int, failure int) {
  77. s.mu.Lock()
  78. defer s.mu.Unlock()
  79. return s.success, s.failure
  80. }
  81. func randStr(size int) string {
  82. data := make([]byte, size)
  83. for i := 0; i < size; i++ {
  84. data[i] = byte(int('a') + rand.Intn(26))
  85. }
  86. return string(data)
  87. }