core/hotspot/rule.go (73 lines of code) (raw):

// Copyright 1999-2020 Alibaba Group Holding Ltd. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hotspot import ( "fmt" "reflect" "strconv" ) // ControlBehavior indicates the traffic shaping behaviour. type ControlBehavior int32 const ( Reject ControlBehavior = iota Throttling ) func (t ControlBehavior) String() string { switch t { case Reject: return "Reject" case Throttling: return "Throttling" default: return strconv.Itoa(int(t)) } } // MetricType represents the target metric type. type MetricType int32 const ( // Concurrency represents concurrency count. Concurrency MetricType = iota // QPS represents request count per second. QPS ) func (t MetricType) String() string { switch t { case Concurrency: return "Concurrency" case QPS: return "QPS" default: return "Undefined" } } // Rule represents the hotspot(frequent) parameter flow control rule type Rule struct { // ID is the unique id ID string `json:"id,omitempty"` // Resource is the resource name Resource string `json:"resource"` // MetricType indicates the metric type for checking logic. // For Concurrency metric, hotspot module will check the each hot parameter's concurrency, // if concurrency exceeds the Threshold, reject the traffic directly. // For QPS metric, hotspot module will check the each hot parameter's QPS, // the ControlBehavior decides the behavior of traffic shaping controller MetricType MetricType `json:"metricType"` // ControlBehavior indicates the traffic shaping behaviour. // ControlBehavior only takes effect when MetricType is QPS ControlBehavior ControlBehavior `json:"controlBehavior"` // ParamIndex is the index in context arguments slice. // if ParamIndex is greater than or equals to zero, ParamIndex means the <ParamIndex>-th parameter // if ParamIndex is the negative, ParamIndex means the reversed <ParamIndex>-th parameter ParamIndex int `json:"paramIndex"` // ParamKey is the key in EntryContext.Input.Attachments map. // ParamKey can be used as a supplement to ParamIndex to facilitate rules to quickly obtain parameter from a large number of parameters // ParamKey is mutually exclusive with ParamIndex, ParamKey has the higher priority than ParamIndex ParamKey string `json:"paramKey"` // Threshold is the threshold to trigger rejection Threshold int64 `json:"threshold"` // MaxQueueingTimeMs only takes effect when ControlBehavior is Throttling and MetricType is QPS MaxQueueingTimeMs int64 `json:"maxQueueingTimeMs"` // BurstCount is the silent count // BurstCount only takes effect when ControlBehavior is Reject and MetricType is QPS BurstCount int64 `json:"burstCount"` // DurationInSec is the time interval in statistic // DurationInSec only takes effect when MetricType is QPS DurationInSec int64 `json:"durationInSec"` // ParamsMaxCapacity is the max capacity of cache statistic ParamsMaxCapacity int64 `json:"paramsMaxCapacity"` // SpecificItems indicates the special threshold for specific value SpecificItems map[interface{}]int64 `json:"specificItems"` } func (r *Rule) String() string { // Return the fallback string return fmt.Sprintf("{Id:%s, Resource:%s, MetricType:%+v, ControlBehavior:%+v, ParamIndex:%d, ParamKey:%s, Threshold:%d, MaxQueueingTimeMs:%d, BurstCount:%d, DurationInSec:%d, ParamsMaxCapacity:%d, SpecificItems:%+v}", r.ID, r.Resource, r.MetricType, r.ControlBehavior, r.ParamIndex, r.ParamKey, r.Threshold, r.MaxQueueingTimeMs, r.BurstCount, r.DurationInSec, r.ParamsMaxCapacity, r.SpecificItems) } func (r *Rule) ResourceName() string { return r.Resource } // IsStatReusable checks whether current rule is "statistically" equal to the given rule. func (r *Rule) IsStatReusable(newRule *Rule) bool { return r.Resource == newRule.Resource && r.ControlBehavior == newRule.ControlBehavior && r.ParamsMaxCapacity == newRule.ParamsMaxCapacity && r.DurationInSec == newRule.DurationInSec && r.MetricType == newRule.MetricType } // Equals checks whether current rule is consistent with the given rule. func (r *Rule) Equals(newRule *Rule) bool { baseCheck := r.Resource == newRule.Resource && r.MetricType == newRule.MetricType && r.ControlBehavior == newRule.ControlBehavior && r.ParamsMaxCapacity == newRule.ParamsMaxCapacity && r.ParamIndex == newRule.ParamIndex && r.ParamKey == newRule.ParamKey && r.Threshold == newRule.Threshold && r.DurationInSec == newRule.DurationInSec && reflect.DeepEqual(r.SpecificItems, newRule.SpecificItems) if !baseCheck { return false } if r.ControlBehavior == Reject { return r.BurstCount == newRule.BurstCount } else if r.ControlBehavior == Throttling { return r.MaxQueueingTimeMs == newRule.MaxQueueingTimeMs } else { return false } }