github.com/lfch/etcd-io/tests/v3@v3.0.0-20221004140520-eac99acd3e9d/functional/tester/stresser.go (about)

     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  
    15  package tester
    16  
    17  import (
    18  	"fmt"
    19  	"time"
    20  
    21  	"github.com/lfch/etcd-io/tests/v3/functional/rpcpb"
    22  
    23  	"go.uber.org/zap"
    24  )
    25  
    26  // Stresser defines stressing client operations.
    27  type Stresser interface {
    28  	// Stress starts to stress the etcd cluster
    29  	Stress() error
    30  	// Pause stops the stresser from sending requests to etcd. Resume by calling Stress.
    31  	Pause() map[string]int
    32  	// Close releases all of the Stresser's resources.
    33  	Close() map[string]int
    34  	// ModifiedKeys reports the number of keys created and deleted by stresser
    35  	ModifiedKeys() int64
    36  }
    37  
    38  // newStresser creates stresser from a comma separated list of stresser types.
    39  func newStresser(clus *Cluster, m *rpcpb.Member) (stressers []Stresser) {
    40  	// TODO: Too intensive stressing clients can panic etcd member with
    41  	// 'out of memory' error. Put rate limits in server side.
    42  	ks := &keyStresser{
    43  		lg:                clus.lg,
    44  		m:                 m,
    45  		keySize:           int(clus.Tester.StressKeySize),
    46  		keyLargeSize:      int(clus.Tester.StressKeySizeLarge),
    47  		keySuffixRange:    int(clus.Tester.StressKeySuffixRange),
    48  		keyTxnSuffixRange: int(clus.Tester.StressKeySuffixRangeTxn),
    49  		keyTxnOps:         int(clus.Tester.StressKeyTxnOps),
    50  		clientsN:          int(clus.Tester.StressClients),
    51  		rateLimiter:       clus.rateLimiter,
    52  	}
    53  	ksExist := false
    54  
    55  	for _, s := range clus.Tester.Stressers {
    56  		clus.lg.Info(
    57  			"creating stresser",
    58  			zap.String("type", s.Type),
    59  			zap.Float64("weight", s.Weight),
    60  			zap.String("endpoint", m.EtcdClientEndpoint),
    61  		)
    62  		switch s.Type {
    63  		case "KV_WRITE_SMALL":
    64  			ksExist = true
    65  			ks.weightKVWriteSmall = s.Weight
    66  		case "KV_WRITE_LARGE":
    67  			ksExist = true
    68  			ks.weightKVWriteLarge = s.Weight
    69  		case "KV_READ_ONE_KEY":
    70  			ksExist = true
    71  			ks.weightKVReadOneKey = s.Weight
    72  		case "KV_READ_RANGE":
    73  			ksExist = true
    74  			ks.weightKVReadRange = s.Weight
    75  		case "KV_DELETE_ONE_KEY":
    76  			ksExist = true
    77  			ks.weightKVDeleteOneKey = s.Weight
    78  		case "KV_DELETE_RANGE":
    79  			ksExist = true
    80  			ks.weightKVDeleteRange = s.Weight
    81  		case "KV_TXN_WRITE_DELETE":
    82  			ksExist = true
    83  			ks.weightKVTxnWriteDelete = s.Weight
    84  
    85  		case "LEASE":
    86  			stressers = append(stressers, &leaseStresser{
    87  				stype:        rpcpb.StresserType_LEASE,
    88  				lg:           clus.lg,
    89  				m:            m,
    90  				numLeases:    10, // TODO: configurable
    91  				keysPerLease: 10, // TODO: configurable
    92  				rateLimiter:  clus.rateLimiter,
    93  			})
    94  
    95  		case "ELECTION_RUNNER":
    96  			reqRate := 100
    97  			args := []string{
    98  				"election",
    99  				fmt.Sprintf("%v", time.Now().UnixNano()), // election name as current nano time
   100  				"--dial-timeout=10s",
   101  				"--endpoints", m.EtcdClientEndpoint,
   102  				"--total-client-connections=10",
   103  				"--rounds=0", // runs forever
   104  				"--req-rate", fmt.Sprintf("%v", reqRate),
   105  			}
   106  			stressers = append(stressers, newRunnerStresser(
   107  				rpcpb.StresserType_ELECTION_RUNNER,
   108  				m.EtcdClientEndpoint,
   109  				clus.lg,
   110  				clus.Tester.RunnerExecPath,
   111  				args,
   112  				clus.rateLimiter,
   113  				reqRate,
   114  			))
   115  
   116  		case "WATCH_RUNNER":
   117  			reqRate := 100
   118  			args := []string{
   119  				"watcher",
   120  				"--prefix", fmt.Sprintf("%v", time.Now().UnixNano()), // prefix all keys with nano time
   121  				"--total-keys=1",
   122  				"--total-prefixes=1",
   123  				"--watch-per-prefix=1",
   124  				"--endpoints", m.EtcdClientEndpoint,
   125  				"--rounds=0", // runs forever
   126  				"--req-rate", fmt.Sprintf("%v", reqRate),
   127  			}
   128  			stressers = append(stressers, newRunnerStresser(
   129  				rpcpb.StresserType_WATCH_RUNNER,
   130  				m.EtcdClientEndpoint,
   131  				clus.lg,
   132  				clus.Tester.RunnerExecPath,
   133  				args,
   134  				clus.rateLimiter,
   135  				reqRate,
   136  			))
   137  
   138  		case "LOCK_RACER_RUNNER":
   139  			reqRate := 100
   140  			args := []string{
   141  				"lock-racer",
   142  				fmt.Sprintf("%v", time.Now().UnixNano()), // locker name as current nano time
   143  				"--endpoints", m.EtcdClientEndpoint,
   144  				"--total-client-connections=10",
   145  				"--rounds=0", // runs forever
   146  				"--req-rate", fmt.Sprintf("%v", reqRate),
   147  			}
   148  			stressers = append(stressers, newRunnerStresser(
   149  				rpcpb.StresserType_LOCK_RACER_RUNNER,
   150  				m.EtcdClientEndpoint,
   151  				clus.lg,
   152  				clus.Tester.RunnerExecPath,
   153  				args,
   154  				clus.rateLimiter,
   155  				reqRate,
   156  			))
   157  
   158  		case "LEASE_RUNNER":
   159  			args := []string{
   160  				"lease-renewer",
   161  				"--ttl=30",
   162  				"--endpoints", m.EtcdClientEndpoint,
   163  			}
   164  			stressers = append(stressers, newRunnerStresser(
   165  				rpcpb.StresserType_LEASE_RUNNER,
   166  				m.EtcdClientEndpoint,
   167  				clus.lg,
   168  				clus.Tester.RunnerExecPath,
   169  				args,
   170  				clus.rateLimiter,
   171  				0,
   172  			))
   173  		}
   174  	}
   175  
   176  	if ksExist {
   177  		return append(stressers, ks)
   178  	}
   179  	return stressers
   180  }