1 /* 2 * 3 * Copyright 2022 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package outlierdetection 19 20 import ( 21 "encoding/json" 22 "time" 23 24 iserviceconfig "google.golang.org/grpc/internal/serviceconfig" 25 "google.golang.org/grpc/serviceconfig" 26 ) 27 28 // SuccessRateEjection is parameters for the success rate ejection algorithm. 29 // This algorithm monitors the request success rate for all endpoints and ejects 30 // individual endpoints whose success rates are statistical outliers. 31 type SuccessRateEjection struct { 32 // StddevFactor is used to determine the ejection threshold for 33 // success rate outlier ejection. The ejection threshold is the difference 34 // between the mean success rate, and the product of this factor and the 35 // standard deviation of the mean success rate: mean - (stdev * 36 // success_rate_stdev_factor). This factor is divided by a thousand to get a 37 // double. That is, if the desired factor is 1.9, the runtime value should 38 // be 1900. Defaults to 1900. 39 StdevFactor uint32 `json:"stdevFactor,omitempty"` 40 // EnforcementPercentage is the % chance that a host will be actually ejected 41 // when an outlier status is detected through success rate statistics. This 42 // setting can be used to disable ejection or to ramp it up slowly. Defaults 43 // to 100. 44 EnforcementPercentage uint32 `json:"enforcementPercentage,omitempty"` 45 // MinimumHosts is the number of hosts in a cluster that must have enough 46 // request volume to detect success rate outliers. If the number of hosts is 47 // less than this setting, outlier detection via success rate statistics is 48 // not performed for any host in the cluster. Defaults to 5. 49 MinimumHosts uint32 `json:"minimumHosts,omitempty"` 50 // RequestVolume is the minimum number of total requests that must be 51 // collected in one interval (as defined by the interval duration above) to 52 // include this host in success rate based outlier detection. If the volume 53 // is lower than this setting, outlier detection via success rate statistics 54 // is not performed for that host. Defaults to 100. 55 RequestVolume uint32 `json:"requestVolume,omitempty"` 56 } 57 58 // For UnmarshalJSON to work correctly and set defaults without infinite 59 // recursion. 60 type successRateEjection SuccessRateEjection 61 62 // UnmarshalJSON unmarshals JSON into SuccessRateEjection. If a 63 // SuccessRateEjection field is not set, that field will get its default value. 64 func (sre *SuccessRateEjection) UnmarshalJSON(j []byte) error { 65 sre.StdevFactor = 1900 66 sre.EnforcementPercentage = 100 67 sre.MinimumHosts = 5 68 sre.RequestVolume = 100 69 // Unmarshal JSON on a type with zero values for methods, including 70 // UnmarshalJSON. Overwrites defaults, leaves alone if not. typecast to 71 // avoid infinite recursion by not recalling this function and causing stack 72 // overflow. 73 return json.Unmarshal(j, (*successRateEjection)(sre)) 74 } 75 76 // Equal returns whether the SuccessRateEjection is the same with the parameter. 77 func (sre *SuccessRateEjection) Equal(sre2 *SuccessRateEjection) bool { 78 if sre == nil && sre2 == nil { 79 return true 80 } 81 if (sre != nil) != (sre2 != nil) { 82 return false 83 } 84 if sre.StdevFactor != sre2.StdevFactor { 85 return false 86 } 87 if sre.EnforcementPercentage != sre2.EnforcementPercentage { 88 return false 89 } 90 if sre.MinimumHosts != sre2.MinimumHosts { 91 return false 92 } 93 return sre.RequestVolume == sre2.RequestVolume 94 } 95 96 // FailurePercentageEjection is parameters for the failure percentage algorithm. 97 // This algorithm ejects individual endpoints whose failure rate is greater than 98 // some threshold, independently of any other endpoint. 99 type FailurePercentageEjection struct { 100 // Threshold is the failure percentage to use when determining failure 101 // percentage-based outlier detection. If the failure percentage of a given 102 // host is greater than or equal to this value, it will be ejected. Defaults 103 // to 85. 104 Threshold uint32 `json:"threshold,omitempty"` 105 // EnforcementPercentage is the % chance that a host will be actually 106 // ejected when an outlier status is detected through failure percentage 107 // statistics. This setting can be used to disable ejection or to ramp it up 108 // slowly. Defaults to 0. 109 EnforcementPercentage uint32 `json:"enforcementPercentage,omitempty"` 110 // MinimumHosts is the minimum number of hosts in a cluster in order to 111 // perform failure percentage-based ejection. If the total number of hosts 112 // in the cluster is less than this value, failure percentage-based ejection 113 // will not be performed. Defaults to 5. 114 MinimumHosts uint32 `json:"minimumHosts,omitempty"` 115 // RequestVolume is the minimum number of total requests that must be 116 // collected in one interval (as defined by the interval duration above) to 117 // perform failure percentage-based ejection for this host. If the volume is 118 // lower than this setting, failure percentage-based ejection will not be 119 // performed for this host. Defaults to 50. 120 RequestVolume uint32 `json:"requestVolume,omitempty"` 121 } 122 123 // For UnmarshalJSON to work correctly and set defaults without infinite 124 // recursion. 125 type failurePercentageEjection FailurePercentageEjection 126 127 // UnmarshalJSON unmarshals JSON into FailurePercentageEjection. If a 128 // FailurePercentageEjection field is not set, that field will get its default 129 // value. 130 func (fpe *FailurePercentageEjection) UnmarshalJSON(j []byte) error { 131 fpe.Threshold = 85 132 fpe.EnforcementPercentage = 0 133 fpe.MinimumHosts = 5 134 fpe.RequestVolume = 50 135 // Unmarshal JSON on a type with zero values for methods, including 136 // UnmarshalJSON. Overwrites defaults, leaves alone if not. typecast to 137 // avoid infinite recursion by not recalling this function and causing stack 138 // overflow. 139 return json.Unmarshal(j, (*failurePercentageEjection)(fpe)) 140 } 141 142 // Equal returns whether the FailurePercentageEjection is the same with the 143 // parameter. 144 func (fpe *FailurePercentageEjection) Equal(fpe2 *FailurePercentageEjection) bool { 145 if fpe == nil && fpe2 == nil { 146 return true 147 } 148 if (fpe != nil) != (fpe2 != nil) { 149 return false 150 } 151 if fpe.Threshold != fpe2.Threshold { 152 return false 153 } 154 if fpe.EnforcementPercentage != fpe2.EnforcementPercentage { 155 return false 156 } 157 if fpe.MinimumHosts != fpe2.MinimumHosts { 158 return false 159 } 160 return fpe.RequestVolume == fpe2.RequestVolume 161 } 162 163 // LBConfig is the config for the outlier detection balancer. 164 type LBConfig struct { 165 serviceconfig.LoadBalancingConfig `json:"-"` 166 // Interval is the time interval between ejection analysis sweeps. This can 167 // result in both new ejections as well as addresses being returned to 168 // service. Defaults to 10s. 169 Interval iserviceconfig.Duration `json:"interval,omitempty"` 170 // BaseEjectionTime is the base time that a host is ejected for. The real 171 // time is equal to the base time multiplied by the number of times the host 172 // has been ejected and is capped by MaxEjectionTime. Defaults to 30s. 173 BaseEjectionTime iserviceconfig.Duration `json:"baseEjectionTime,omitempty"` 174 // MaxEjectionTime is the maximum time that an address is ejected for. If 175 // not specified, the default value (300s) or the BaseEjectionTime value is 176 // applied, whichever is larger. 177 MaxEjectionTime iserviceconfig.Duration `json:"maxEjectionTime,omitempty"` 178 // MaxEjectionPercent is the maximum % of an upstream cluster that can be 179 // ejected due to outlier detection. Defaults to 10% but will eject at least 180 // one host regardless of the value. 181 MaxEjectionPercent uint32 `json:"maxEjectionPercent,omitempty"` 182 // SuccessRateEjection is the parameters for the success rate ejection 183 // algorithm. If set, success rate ejections will be performed. 184 SuccessRateEjection *SuccessRateEjection `json:"successRateEjection,omitempty"` 185 // FailurePercentageEjection is the parameters for the failure percentage 186 // algorithm. If set, failure rate ejections will be performed. 187 FailurePercentageEjection *FailurePercentageEjection `json:"failurePercentageEjection,omitempty"` 188 // ChildPolicy is the config for the child policy. 189 ChildPolicy *iserviceconfig.BalancerConfig `json:"childPolicy,omitempty"` 190 } 191 192 // For UnmarshalJSON to work correctly and set defaults without infinite 193 // recursion. 194 type lbConfig LBConfig 195 196 // UnmarshalJSON unmarshals JSON into LBConfig. If a top level LBConfig field 197 // (i.e. not next layer sre or fpe) is not set, that field will get its default 198 // value. If sre or fpe is not set, it will stay unset, otherwise it will 199 // unmarshal on those types populating with default values for their fields if 200 // needed. 201 func (lbc *LBConfig) UnmarshalJSON(j []byte) error { 202 // Default top layer values as documented in A50. 203 lbc.Interval = iserviceconfig.Duration(10 * time.Second) 204 lbc.BaseEjectionTime = iserviceconfig.Duration(30 * time.Second) 205 lbc.MaxEjectionTime = iserviceconfig.Duration(300 * time.Second) 206 lbc.MaxEjectionPercent = 10 207 // Unmarshal JSON on a type with zero values for methods, including 208 // UnmarshalJSON. Overwrites defaults, leaves alone if not. typecast to 209 // avoid infinite recursion by not recalling this function and causing stack 210 // overflow. 211 return json.Unmarshal(j, (*lbConfig)(lbc)) 212 } 213 214 // EqualIgnoringChildPolicy returns whether the LBConfig is same with the 215 // parameter outside of the child policy, only comparing the Outlier Detection 216 // specific configuration. 217 func (lbc *LBConfig) EqualIgnoringChildPolicy(lbc2 *LBConfig) bool { 218 if lbc == nil && lbc2 == nil { 219 return true 220 } 221 if (lbc != nil) != (lbc2 != nil) { 222 return false 223 } 224 if lbc.Interval != lbc2.Interval { 225 return false 226 } 227 if lbc.BaseEjectionTime != lbc2.BaseEjectionTime { 228 return false 229 } 230 if lbc.MaxEjectionTime != lbc2.MaxEjectionTime { 231 return false 232 } 233 if lbc.MaxEjectionPercent != lbc2.MaxEjectionPercent { 234 return false 235 } 236 if !lbc.SuccessRateEjection.Equal(lbc2.SuccessRateEjection) { 237 return false 238 } 239 return lbc.FailurePercentageEjection.Equal(lbc2.FailurePercentageEjection) 240 } 241