core/flow/rule.go (113 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 flow import ( "encoding/json" "fmt" "github.com/alibaba/sentinel-golang/util" ) // RelationStrategy indicates the flow control strategy based on the relation of invocations. type RelationStrategy int32 const ( // CurrentResource means flow control by current resource directly. CurrentResource RelationStrategy = iota // AssociatedResource means flow control by the associated resource rather than current resource. AssociatedResource ) func (s RelationStrategy) String() string { switch s { case CurrentResource: return "CurrentResource" case AssociatedResource: return "AssociatedResource" default: return "Undefined" } } type TokenCalculateStrategy int32 const ( Direct TokenCalculateStrategy = iota WarmUp MemoryAdaptive ) func (s TokenCalculateStrategy) String() string { switch s { case Direct: return "Direct" case WarmUp: return "WarmUp" case MemoryAdaptive: return "MemoryAdaptive" default: return "Undefined" } } // ControlBehavior defines the behavior when requests have reached the capacity of the resource. type ControlBehavior int32 const ( Reject ControlBehavior = iota // Throttling indicates that pending requests will be throttled, wait in queue (until free capacity is available) Throttling ) func (s ControlBehavior) String() string { switch s { case Reject: return "Reject" case Throttling: return "Throttling" default: return "Undefined" } } // Rule describes the strategy of flow control, the flow control strategy is based on QPS statistic metric type Rule struct { // ID represents the unique ID of the rule (optional). ID string `json:"id,omitempty"` // Resource represents the resource name. Resource string `json:"resource"` TokenCalculateStrategy TokenCalculateStrategy `json:"tokenCalculateStrategy"` ControlBehavior ControlBehavior `json:"controlBehavior"` // Threshold means the threshold during StatIntervalInMs // If StatIntervalInMs is 1000(1 second), Threshold means QPS Threshold float64 `json:"threshold"` RelationStrategy RelationStrategy `json:"relationStrategy"` RefResource string `json:"refResource"` // MaxQueueingTimeMs only takes effect when ControlBehavior is Throttling. // When MaxQueueingTimeMs is 0, it means Throttling only controls interval of requests, // and requests exceeding the threshold will be rejected directly. MaxQueueingTimeMs uint32 `json:"maxQueueingTimeMs"` WarmUpPeriodSec uint32 `json:"warmUpPeriodSec"` WarmUpColdFactor uint32 `json:"warmUpColdFactor"` // StatIntervalInMs indicates the statistic interval and it's the optional setting for flow Rule. // If user doesn't set StatIntervalInMs, that means using default metric statistic of resource. // If the StatIntervalInMs user specifies can not reuse the global statistic of resource, // sentinel will generate independent statistic structure for this rule. StatIntervalInMs uint32 `json:"statIntervalInMs"` // adaptive flow control algorithm related parameters // limitation: LowMemUsageThreshold > HighMemUsageThreshold && MemHighWaterMarkBytes > MemLowWaterMarkBytes // if the current memory usage is less than or equals to MemLowWaterMarkBytes, threshold == LowMemUsageThreshold // if the current memory usage is more than or equals to MemHighWaterMarkBytes, threshold == HighMemUsageThreshold // if the current memory usage is in (MemLowWaterMarkBytes, MemHighWaterMarkBytes), threshold is in (HighMemUsageThreshold, LowMemUsageThreshold) LowMemUsageThreshold int64 `json:"lowMemUsageThreshold"` HighMemUsageThreshold int64 `json:"highMemUsageThreshold"` MemLowWaterMarkBytes int64 `json:"memLowWaterMarkBytes"` MemHighWaterMarkBytes int64 `json:"memHighWaterMarkBytes"` } func (r *Rule) isEqualsTo(newRule *Rule) bool { if newRule == nil { return false } if !(r.Resource == newRule.Resource && r.RelationStrategy == newRule.RelationStrategy && r.RefResource == newRule.RefResource && r.StatIntervalInMs == newRule.StatIntervalInMs && r.TokenCalculateStrategy == newRule.TokenCalculateStrategy && r.ControlBehavior == newRule.ControlBehavior && util.Float64Equals(r.Threshold, newRule.Threshold) && r.MaxQueueingTimeMs == newRule.MaxQueueingTimeMs && r.WarmUpPeriodSec == newRule.WarmUpPeriodSec && r.WarmUpColdFactor == newRule.WarmUpColdFactor && r.LowMemUsageThreshold == newRule.LowMemUsageThreshold && r.HighMemUsageThreshold == newRule.HighMemUsageThreshold && r.MemLowWaterMarkBytes == newRule.MemLowWaterMarkBytes && r.MemHighWaterMarkBytes == newRule.MemHighWaterMarkBytes) { return false } return true } func (r *Rule) isStatReusable(newRule *Rule) bool { if newRule == nil { return false } return r.Resource == newRule.Resource && r.RelationStrategy == newRule.RelationStrategy && r.RefResource == newRule.RefResource && r.StatIntervalInMs == newRule.StatIntervalInMs && r.needStatistic() && newRule.needStatistic() } func (r *Rule) needStatistic() bool { return r.TokenCalculateStrategy == WarmUp || r.ControlBehavior == Reject } func (r *Rule) String() string { b, err := json.Marshal(r) if err != nil { // Return the fallback string return fmt.Sprintf("Rule{Resource=%s, TokenCalculateStrategy=%s, ControlBehavior=%s, "+ "Threshold=%.2f, RelationStrategy=%s, RefResource=%s, MaxQueueingTimeMs=%d, WarmUpPeriodSec=%d, WarmUpColdFactor=%d, StatIntervalInMs=%d, "+ "LowMemUsageThreshold=%v, HighMemUsageThreshold=%v, MemLowWaterMarkBytes=%v, MemHighWaterMarkBytes=%v}", r.Resource, r.TokenCalculateStrategy, r.ControlBehavior, r.Threshold, r.RelationStrategy, r.RefResource, r.MaxQueueingTimeMs, r.WarmUpPeriodSec, r.WarmUpColdFactor, r.StatIntervalInMs, r.LowMemUsageThreshold, r.HighMemUsageThreshold, r.MemLowWaterMarkBytes, r.MemHighWaterMarkBytes) } return string(b) } func (r *Rule) ResourceName() string { return r.Resource }