mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
etcd-tester: move stresser and checker to tester
These really belong in tester code; the stressers and checkers are higher order operations that are orchestrated by the tester. They're not really cluster primitives.
This commit is contained in:
parent
4a08678ce1
commit
86c4a74139
@ -39,17 +39,9 @@ type agentConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type cluster struct {
|
type cluster struct {
|
||||||
agents []agentConfig
|
agents []agentConfig
|
||||||
|
v2Only bool // to be deprecated
|
||||||
v2Only bool // to be deprecated
|
Size int
|
||||||
consistencyCheck bool
|
|
||||||
Size int
|
|
||||||
|
|
||||||
Stressers []Stresser
|
|
||||||
stressBuilder stressBuilder
|
|
||||||
leaseStresserBuilder leaseStresserBuilder
|
|
||||||
Checker Checker
|
|
||||||
|
|
||||||
Members []*member
|
Members []*member
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,27 +92,6 @@ func (c *cluster) bootstrap() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Stressers = make([]Stresser, 0)
|
|
||||||
leaseStressers := make([]Stresser, len(members))
|
|
||||||
for i, m := range members {
|
|
||||||
lStresser := c.leaseStresserBuilder(m)
|
|
||||||
leaseStressers[i] = lStresser
|
|
||||||
c.Stressers = append(c.Stressers, c.stressBuilder(m), lStresser)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range c.Stressers {
|
|
||||||
go c.Stressers[i].Stress()
|
|
||||||
}
|
|
||||||
|
|
||||||
var checkers []Checker
|
|
||||||
if c.consistencyCheck && !c.v2Only {
|
|
||||||
checkers = append(checkers, newHashChecker(hashAndRevGetter(c)), newLeaseChecker(leaseStressers))
|
|
||||||
} else {
|
|
||||||
checkers = append(checkers, newNoChecker())
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Checker = newCompositeChecker(checkers)
|
|
||||||
|
|
||||||
c.Size = size
|
c.Size = size
|
||||||
c.Members = members
|
c.Members = members
|
||||||
return nil
|
return nil
|
||||||
@ -167,15 +138,6 @@ func (c *cluster) GetLeader() (int, error) {
|
|||||||
return 0, fmt.Errorf("no leader found")
|
return 0, fmt.Errorf("no leader found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cluster) Report() (success, failure int) {
|
|
||||||
for _, stress := range c.Stressers {
|
|
||||||
s, f := stress.Report()
|
|
||||||
success += s
|
|
||||||
failure += f
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cluster) Cleanup() error {
|
func (c *cluster) Cleanup() error {
|
||||||
var lasterr error
|
var lasterr error
|
||||||
for _, m := range c.Members {
|
for _, m := range c.Members {
|
||||||
@ -183,10 +145,6 @@ func (c *cluster) Cleanup() error {
|
|||||||
lasterr = err
|
lasterr = err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, s := range c.Stressers {
|
|
||||||
s.Cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
return lasterr
|
return lasterr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,9 +152,6 @@ func (c *cluster) Terminate() {
|
|||||||
for _, m := range c.Members {
|
for _, m := range c.Members {
|
||||||
m.Agent.Terminate()
|
m.Agent.Terminate()
|
||||||
}
|
}
|
||||||
for _, s := range c.Stressers {
|
|
||||||
s.Cancel()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cluster) Status() ClusterStatus {
|
func (c *cluster) Status() ClusterStatus {
|
||||||
@ -217,6 +172,22 @@ func (c *cluster) Status() ClusterStatus {
|
|||||||
return cs
|
return cs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *cluster) maxRev() (rev int64, err error) {
|
||||||
|
for _, m := range c.Members {
|
||||||
|
curRev, _, curErr := m.RevHash()
|
||||||
|
if curErr != nil {
|
||||||
|
err = curErr
|
||||||
|
}
|
||||||
|
if curRev > rev {
|
||||||
|
rev = curRev
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rev == 0 {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return rev, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *cluster) getRevisionHash() (map[string]int64, map[string]int64, error) {
|
func (c *cluster) getRevisionHash() (map[string]int64, map[string]int64, error) {
|
||||||
revs := make(map[string]int64)
|
revs := make(map[string]int64)
|
||||||
hashes := make(map[string]int64)
|
hashes := make(map[string]int64)
|
||||||
|
@ -136,26 +136,29 @@ func (f *failureUntilSnapshot) Inject(c *cluster, round int) error {
|
|||||||
if err := f.failure.Inject(c, round); err != nil {
|
if err := f.failure.Inject(c, round); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Size < 3 {
|
if c.Size < 3 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
startRev, err := c.maxRev()
|
||||||
start, _ := c.Report()
|
if err != nil {
|
||||||
end := start
|
return err
|
||||||
|
}
|
||||||
|
lastRev := startRev
|
||||||
// Normal healthy cluster could accept 1000req/s at least.
|
// Normal healthy cluster could accept 1000req/s at least.
|
||||||
// Give it 3-times time to create a new snapshot.
|
// Give it 3-times time to create a new snapshot.
|
||||||
retry := snapshotCount / 1000 * 3
|
retry := snapshotCount / 1000 * 3
|
||||||
for j := 0; j < retry; j++ {
|
for j := 0; j < retry; j++ {
|
||||||
end, _ = c.Report()
|
if lastRev, err = c.maxRev(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
// If the number of proposals committed is bigger than snapshot count,
|
// If the number of proposals committed is bigger than snapshot count,
|
||||||
// a new snapshot should have been created.
|
// a new snapshot should have been created.
|
||||||
if end-start > snapshotCount {
|
if lastRev-startRev > snapshotCount {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cluster too slow: only commit %d requests in %ds", end-start, retry)
|
return fmt.Errorf("cluster too slow: only commit %d requests in %ds", lastRev-startRev, retry)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *failureUntilSnapshot) Desc() string {
|
func (f *failureUntilSnapshot) Desc() string {
|
||||||
|
@ -67,26 +67,9 @@ func main() {
|
|||||||
agents[i].datadir = *datadir
|
agents[i].datadir = *datadir
|
||||||
}
|
}
|
||||||
|
|
||||||
sConfig := &stressConfig{
|
|
||||||
qps: *stressQPS,
|
|
||||||
keyLargeSize: int(*stressKeyLargeSize),
|
|
||||||
keySize: int(*stressKeySize),
|
|
||||||
keySuffixRange: int(*stressKeySuffixRange),
|
|
||||||
v2: *isV2Only,
|
|
||||||
}
|
|
||||||
|
|
||||||
lsConfig := &leaseStressConfig{
|
|
||||||
numLeases: 10,
|
|
||||||
keysPerLease: 10,
|
|
||||||
qps: *stressQPS, // only used to create nop stresser in leaseStresserBuilder
|
|
||||||
}
|
|
||||||
|
|
||||||
c := &cluster{
|
c := &cluster{
|
||||||
agents: agents,
|
agents: agents,
|
||||||
v2Only: *isV2Only,
|
v2Only: *isV2Only,
|
||||||
stressBuilder: newStressBuilder(*stresserType, sConfig),
|
|
||||||
leaseStresserBuilder: newLeaseStresserBuilder(*stresserType, lsConfig),
|
|
||||||
consistencyCheck: *consistencyCheck,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.bootstrap(); err != nil {
|
if err := c.bootstrap(); err != nil {
|
||||||
@ -129,10 +112,26 @@ func main() {
|
|||||||
schedule[i] = failures[caseNum]
|
schedule[i] = failures[caseNum]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sConfig := &stressConfig{
|
||||||
|
qps: *stressQPS,
|
||||||
|
keyLargeSize: int(*stressKeyLargeSize),
|
||||||
|
keySize: int(*stressKeySize),
|
||||||
|
keySuffixRange: int(*stressKeySuffixRange),
|
||||||
|
v2: *isV2Only,
|
||||||
|
}
|
||||||
|
lsConfig := &leaseStressConfig{
|
||||||
|
numLeases: 10,
|
||||||
|
keysPerLease: 10,
|
||||||
|
qps: *stressQPS,
|
||||||
|
}
|
||||||
t := &tester{
|
t := &tester{
|
||||||
failures: schedule,
|
failures: schedule,
|
||||||
cluster: c,
|
cluster: c,
|
||||||
limit: *limit,
|
limit: *limit,
|
||||||
|
stressBuilder: newStressBuilder(*stresserType, sConfig),
|
||||||
|
leaseStresserBuilder: newLeaseStresserBuilder(*stresserType, lsConfig),
|
||||||
|
consistencyCheck: *consistencyCheck,
|
||||||
}
|
}
|
||||||
|
|
||||||
sh := statusHandler{status: &t.status}
|
sh := statusHandler{status: &t.status}
|
||||||
|
@ -25,6 +25,12 @@ type tester struct {
|
|||||||
limit int
|
limit int
|
||||||
status Status
|
status Status
|
||||||
currentRevision int64
|
currentRevision int64
|
||||||
|
|
||||||
|
Stressers []Stresser
|
||||||
|
stressBuilder stressBuilder
|
||||||
|
leaseStresserBuilder leaseStresserBuilder
|
||||||
|
Checker Checker
|
||||||
|
consistencyCheck bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// compactQPS is rough number of compact requests per second.
|
// compactQPS is rough number of compact requests per second.
|
||||||
@ -39,6 +45,8 @@ func (tt *tester) runLoop() {
|
|||||||
tt.status.Failures = append(tt.status.Failures, f.Desc())
|
tt.status.Failures = append(tt.status.Failures, f.Desc())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tt.setupStressers()
|
||||||
|
|
||||||
var prevCompactRev int64
|
var prevCompactRev int64
|
||||||
for round := 0; round < tt.limit || tt.limit == -1; round++ {
|
for round := 0; round < tt.limit || tt.limit == -1; round++ {
|
||||||
tt.status.setRound(round)
|
tt.status.setRound(round)
|
||||||
@ -82,6 +90,27 @@ func (tt *tester) runLoop() {
|
|||||||
plog.Printf("%s functional-tester is finished", tt.logPrefix())
|
plog.Printf("%s functional-tester is finished", tt.logPrefix())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tt *tester) setupStressers() {
|
||||||
|
tt.Stressers = make([]Stresser, 0)
|
||||||
|
leaseStressers := make([]Stresser, 0, 2*len(tt.cluster.Members))
|
||||||
|
for i, m := range tt.cluster.Members {
|
||||||
|
lStresser := tt.leaseStresserBuilder(m)
|
||||||
|
leaseStressers[i] = lStresser
|
||||||
|
tt.Stressers = append(tt.Stressers, tt.stressBuilder(m), lStresser)
|
||||||
|
}
|
||||||
|
for i := range tt.Stressers {
|
||||||
|
go tt.Stressers[i].Stress()
|
||||||
|
}
|
||||||
|
if !tt.consistencyCheck || tt.cluster.v2Only {
|
||||||
|
tt.Checker = newNoChecker()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tt.Checker = newCompositeChecker([]Checker{
|
||||||
|
newHashChecker(hashAndRevGetter(tt.cluster)),
|
||||||
|
newLeaseChecker(leaseStressers)},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func (tt *tester) doRound(round int) error {
|
func (tt *tester) doRound(round int) error {
|
||||||
for j, f := range tt.failures {
|
for j, f := range tt.failures {
|
||||||
caseTotalCounter.WithLabelValues(f.Desc()).Inc()
|
caseTotalCounter.WithLabelValues(f.Desc()).Inc()
|
||||||
@ -142,7 +171,7 @@ func (tt *tester) checkConsistency() (err error) {
|
|||||||
}
|
}
|
||||||
err = tt.startStressers()
|
err = tt.startStressers()
|
||||||
}()
|
}()
|
||||||
if err = tt.cluster.Checker.Check(); err != nil {
|
if err = tt.Checker.Check(); err != nil {
|
||||||
plog.Printf("%s %v", tt.logPrefix(), err)
|
plog.Printf("%s %v", tt.logPrefix(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,6 +236,7 @@ func (tt *tester) cleanup() error {
|
|||||||
}
|
}
|
||||||
caseFailedTotalCounter.WithLabelValues(desc).Inc()
|
caseFailedTotalCounter.WithLabelValues(desc).Inc()
|
||||||
|
|
||||||
|
tt.cancelStressers()
|
||||||
plog.Printf("%s cleaning up...", tt.logPrefix())
|
plog.Printf("%s cleaning up...", tt.logPrefix())
|
||||||
if err := tt.cluster.Cleanup(); err != nil {
|
if err := tt.cluster.Cleanup(); err != nil {
|
||||||
plog.Warningf("%s cleanup error: %v", tt.logPrefix(), err)
|
plog.Warningf("%s cleanup error: %v", tt.logPrefix(), err)
|
||||||
@ -223,7 +253,7 @@ func (tt *tester) cleanup() error {
|
|||||||
|
|
||||||
func (tt *tester) cancelStressers() {
|
func (tt *tester) cancelStressers() {
|
||||||
plog.Printf("%s canceling the stressers...", tt.logPrefix())
|
plog.Printf("%s canceling the stressers...", tt.logPrefix())
|
||||||
for _, s := range tt.cluster.Stressers {
|
for _, s := range tt.Stressers {
|
||||||
s.Cancel()
|
s.Cancel()
|
||||||
}
|
}
|
||||||
plog.Printf("%s canceled stressers", tt.logPrefix())
|
plog.Printf("%s canceled stressers", tt.logPrefix())
|
||||||
@ -231,7 +261,7 @@ func (tt *tester) cancelStressers() {
|
|||||||
|
|
||||||
func (tt *tester) startStressers() error {
|
func (tt *tester) startStressers() error {
|
||||||
plog.Printf("%s starting the stressers...", tt.logPrefix())
|
plog.Printf("%s starting the stressers...", tt.logPrefix())
|
||||||
for _, s := range tt.cluster.Stressers {
|
for _, s := range tt.Stressers {
|
||||||
if err := s.Stress(); err != nil {
|
if err := s.Stress(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -239,3 +269,12 @@ func (tt *tester) startStressers() error {
|
|||||||
plog.Printf("%s started stressers", tt.logPrefix())
|
plog.Printf("%s started stressers", tt.logPrefix())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tt *tester) Report() (success, failure int) {
|
||||||
|
for _, stresser := range tt.Stressers {
|
||||||
|
s, f := stresser.Report()
|
||||||
|
success += s
|
||||||
|
failure += f
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user