stress.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // Copyright 2018 The etcd Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package tester
  15. import (
  16. "fmt"
  17. "time"
  18. "go.uber.org/zap"
  19. )
  20. // Stresser defines stressing client operations.
  21. type Stresser interface {
  22. // Stress starts to stress the etcd cluster
  23. Stress() error
  24. // Pause stops the stresser from sending requests to etcd. Resume by calling Stress.
  25. Pause()
  26. // Close releases all of the Stresser's resources.
  27. Close()
  28. // ModifiedKeys reports the number of keys created and deleted by stresser
  29. ModifiedKeys() int64
  30. // Checker returns an invariant checker for after the stresser is canceled.
  31. Checker() Checker
  32. }
  33. // newStresser creates stresser from a comma separated list of stresser types.
  34. func newStresser(clus *Cluster, idx int) Stresser {
  35. stressers := make([]Stresser, len(clus.Tester.StressTypes))
  36. for i, stype := range clus.Tester.StressTypes {
  37. clus.lg.Info("creating stresser", zap.String("type", stype))
  38. switch stype {
  39. case "NO_STRESS":
  40. stressers[i] = &nopStresser{start: time.Now(), qps: int(clus.rateLimiter.Limit())}
  41. case "KV":
  42. // TODO: Too intensive stressing clients can panic etcd member with
  43. // 'out of memory' error. Put rate limits in server side.
  44. stressers[i] = &keyStresser{
  45. lg: clus.lg,
  46. m: clus.Members[idx],
  47. keySize: int(clus.Tester.StressKeySize),
  48. keyLargeSize: int(clus.Tester.StressKeySizeLarge),
  49. keySuffixRange: int(clus.Tester.StressKeySuffixRange),
  50. keyTxnSuffixRange: int(clus.Tester.StressKeySuffixRangeTxn),
  51. keyTxnOps: int(clus.Tester.StressKeyTxnOps),
  52. N: 100,
  53. rateLimiter: clus.rateLimiter,
  54. }
  55. case "LEASE":
  56. stressers[i] = &leaseStresser{
  57. lg: clus.lg,
  58. m: clus.Members[idx],
  59. numLeases: 10, // TODO: configurable
  60. keysPerLease: 10, // TODO: configurable
  61. rateLimiter: clus.rateLimiter,
  62. }
  63. case "ELECTION_RUNNER":
  64. reqRate := 100
  65. args := []string{
  66. "election",
  67. fmt.Sprintf("%v", time.Now().UnixNano()), // election name as current nano time
  68. "--dial-timeout=10s",
  69. "--endpoints", clus.Members[idx].EtcdClientEndpoint,
  70. "--total-client-connections=10",
  71. "--rounds=0", // runs forever
  72. "--req-rate", fmt.Sprintf("%v", reqRate),
  73. }
  74. stressers[i] = newRunnerStresser(
  75. clus.Tester.RunnerExecPath,
  76. args,
  77. clus.rateLimiter,
  78. reqRate,
  79. )
  80. case "WATCH_RUNNER":
  81. reqRate := 100
  82. args := []string{
  83. "watcher",
  84. "--prefix", fmt.Sprintf("%v", time.Now().UnixNano()), // prefix all keys with nano time
  85. "--total-keys=1",
  86. "--total-prefixes=1",
  87. "--watch-per-prefix=1",
  88. "--endpoints", clus.Members[idx].EtcdClientEndpoint,
  89. "--rounds=0", // runs forever
  90. "--req-rate", fmt.Sprintf("%v", reqRate),
  91. }
  92. stressers[i] = newRunnerStresser(clus.Tester.RunnerExecPath, args, clus.rateLimiter, reqRate)
  93. case "LOCK_RACER_RUNNER":
  94. reqRate := 100
  95. args := []string{
  96. "lock-racer",
  97. fmt.Sprintf("%v", time.Now().UnixNano()), // locker name as current nano time
  98. "--endpoints", clus.Members[idx].EtcdClientEndpoint,
  99. "--total-client-connections=10",
  100. "--rounds=0", // runs forever
  101. "--req-rate", fmt.Sprintf("%v", reqRate),
  102. }
  103. stressers[i] = newRunnerStresser(clus.Tester.RunnerExecPath, args, clus.rateLimiter, reqRate)
  104. case "LEASE_RUNNER":
  105. args := []string{
  106. "lease-renewer",
  107. "--ttl=30",
  108. "--endpoints", clus.Members[idx].EtcdClientEndpoint,
  109. }
  110. stressers[i] = newRunnerStresser(clus.Tester.RunnerExecPath, args, clus.rateLimiter, 0)
  111. }
  112. }
  113. return &compositeStresser{stressers}
  114. }