@@ -67,28 +67,54 @@ func stringp(s string) *string { return &s }
6767
6868var (
6969 perCallConfig = iwrr.LBConfig {
70+ EnableOOBLoadReport : boolp (false ),
71+ OOBReportingPeriod : stringp ("0.005s" ),
72+ BlackoutPeriod : stringp ("0s" ),
73+ WeightExpirationPeriod : stringp ("60s" ),
74+ WeightUpdatePeriod : stringp (".050s" ),
75+ ErrorUtilizationPenalty : float64p (0. ),
76+ }
77+ perCallConfigWithSlowStart = iwrr.LBConfig {
7078 EnableOOBLoadReport : boolp (false ),
7179 OOBReportingPeriod : stringp ("0.005s" ),
7280 BlackoutPeriod : stringp ("0s" ),
7381 WeightExpirationPeriod : stringp ("60s" ),
7482 WeightUpdatePeriod : stringp (".050s" ),
7583 ErrorUtilizationPenalty : float64p (0 ),
84+ SlowStartConfig : & iwrr.SlowStartConfig {
85+ SlowStartWindow : stringp ("30s" ),
86+ Aggression : float64p (1.0 ),
87+ MinWeightPercent : float64p (10.0 ),
88+ },
7689 }
7790 oobConfig = iwrr.LBConfig {
7891 EnableOOBLoadReport : boolp (true ),
7992 OOBReportingPeriod : stringp ("0.005s" ),
8093 BlackoutPeriod : stringp ("0s" ),
8194 WeightExpirationPeriod : stringp ("60s" ),
8295 WeightUpdatePeriod : stringp (".050s" ),
83- ErrorUtilizationPenalty : float64p (0 ),
96+ ErrorUtilizationPenalty : float64p (0. ),
97+ }
98+ oobConfigWithSlowStart = iwrr.LBConfig {
99+ EnableOOBLoadReport : boolp (true ),
100+ OOBReportingPeriod : stringp ("0.005s" ),
101+ BlackoutPeriod : stringp ("0s" ),
102+ WeightExpirationPeriod : stringp ("60s" ),
103+ WeightUpdatePeriod : stringp (".050s" ),
104+ ErrorUtilizationPenalty : float64p (0. ),
105+ SlowStartConfig : & iwrr.SlowStartConfig {
106+ SlowStartWindow : stringp ("30s" ),
107+ Aggression : float64p (1.0 ),
108+ MinWeightPercent : float64p (10.0 ),
109+ },
84110 }
85111 testMetricsConfig = iwrr.LBConfig {
86112 EnableOOBLoadReport : boolp (false ),
87113 OOBReportingPeriod : stringp ("0.005s" ),
88114 BlackoutPeriod : stringp ("0s" ),
89115 WeightExpirationPeriod : stringp ("60s" ),
90116 WeightUpdatePeriod : stringp ("30s" ),
91- ErrorUtilizationPenalty : float64p (0 ),
117+ ErrorUtilizationPenalty : float64p (0.0 ),
92118 }
93119)
94120
@@ -176,8 +202,11 @@ func (s) TestBalancer_OneAddress(t *testing.T) {
176202 cfg iwrr.LBConfig
177203 }{
178204 {rt : reportNone , cfg : perCallConfig },
205+ {rt : reportCall , cfg : perCallConfigWithSlowStart },
179206 {rt : reportCall , cfg : perCallConfig },
207+ {rt : reportCall , cfg : perCallConfigWithSlowStart },
180208 {rt : reportOOB , cfg : oobConfig },
209+ {rt : reportOOB , cfg : oobConfigWithSlowStart },
181210 }
182211
183212 for _ , tc := range testCases {
@@ -652,6 +681,66 @@ func (s) TestBalancer_TwoAddresses_BlackoutPeriod(t *testing.T) {
652681 }
653682}
654683
684+ func (s ) TestBalancer_SlowStart (t * testing.T ) {
685+ ctx , cancel := context .WithTimeout (context .Background (), defaultTestTimeout )
686+ defer cancel ()
687+
688+ srv1 := startServer (t , reportBoth )
689+ srv2 := startServer (t , reportBoth )
690+ srv3 := startServer (t , reportBoth )
691+
692+ // srv1, srv2, srv3 all start loaded equally.
693+ srv1 .oobMetrics .SetQPS (10.0 )
694+ srv1 .oobMetrics .SetApplicationUtilization (1.0 )
695+
696+ srv2 .oobMetrics .SetQPS (10.0 )
697+ srv2 .oobMetrics .SetApplicationUtilization (1.0 )
698+
699+ srv3 .oobMetrics .SetQPS (10.0 )
700+ srv3 .oobMetrics .SetApplicationUtilization (1.0 )
701+
702+ slowStartPeriod := 2 * time .Second
703+ slowStartConfig := & iwrr.SlowStartConfig {
704+ SlowStartWindow : stringp ("2s" ),
705+ Aggression : float64p (1.0 ),
706+ MinWeightPercent : float64p (10.0 ),
707+ }
708+ cfg := oobConfig
709+ cfg .BlackoutPeriod = stringp ("0.1s" )
710+ cfg .SlowStartConfig = slowStartConfig
711+ sc := svcConfig (t , cfg )
712+
713+ if err := srv1 .StartClient (grpc .WithDefaultServiceConfig (sc )); err != nil {
714+ t .Fatalf ("Error starting client: %v" , err )
715+ }
716+
717+ addrs := []resolver.Address {{Addr : srv1 .Address }, {Addr : srv2 .Address }}
718+ srv1 .R .UpdateState (resolver.State {Addresses : addrs })
719+
720+ // Call each backend once to ensure the weights have been received.
721+ ensureReached (ctx , t , srv1 .Client , 2 )
722+ time .Sleep (slowStartPeriod + weightUpdatePeriod )
723+ checkWeights (ctx , t , srvWeight {srv1 , 10 }, srvWeight {srv2 , 10 })
724+
725+ // Add backend 3
726+ addrs = append (addrs , resolver.Address {Addr : srv3 .Address })
727+ srv1 .R .UpdateState (resolver.State {Addresses : addrs })
728+ ensureReached (ctx , t , srv1 .Client , 3 )
729+
730+ // validate that srv3 is in slow start
731+ time .Sleep (weightUpdatePeriod )
732+ checkWeights (ctx , t , srvWeight {srv1 , 10 }, srvWeight {srv2 , 10 }, srvWeight {srv3 , 5 })
733+
734+ // validate that srv3 exits slow start
735+ time .Sleep (slowStartPeriod + weightUpdatePeriod )
736+ checkWeights (ctx , t , srvWeight {srv1 , 10 }, srvWeight {srv2 , 10 }, srvWeight {srv3 , 10 })
737+ fmt .Printf ("Test log ---------------------> End\n " )
738+ if srv1 .CC != nil {
739+ srv1 .CC .Close ()
740+ time .Sleep (weightUpdatePeriod ) // Wait for cleanup
741+ }
742+ }
743+
655744// Tests that the weight expiration period causes backends to use 0 as their
656745// weight (meaning to use the average weight) once the expiration period
657746// elapses.
@@ -789,7 +878,9 @@ func (s) TestBalancer_AddressesChanging(t *testing.T) {
789878func ensureReached (ctx context.Context , t * testing.T , c testgrpc.TestServiceClient , n int ) {
790879 t .Helper ()
791880 reached := make (map [string ]struct {})
881+ i := 0
792882 for len (reached ) != n {
883+ i ++
793884 var peer peer.Peer
794885 if _ , err := c .EmptyCall (ctx , & testpb.Empty {}, grpc .Peer (& peer )); err != nil {
795886 t .Fatalf ("Error from EmptyCall: %v" , err )
0 commit comments