-
Notifications
You must be signed in to change notification settings - Fork 438
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
frequency parameters traffic control #119
frequency parameters traffic control #119
Conversation
Codecov Report
@@ Coverage Diff @@
## master #119 +/- ##
==========================================
- Coverage 43.48% 41.74% -1.75%
==========================================
Files 67 74 +7
Lines 2863 3507 +644
==========================================
+ Hits 1245 1464 +219
- Misses 1479 1865 +386
- Partials 139 178 +39
Continue to review full report at Codecov.
|
9b64632
to
14a48a7
Compare
core/stat/stat_slot_callback.go
Outdated
callbackUpdateMux = new(sync.RWMutex) | ||
) | ||
|
||
type StatSlotEntryCallback interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the stat slot callback is not needed? Just make it as another StatSlot
and add it to slot chain is okay :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding a new StatSlot to record the concurrency statistic seems make more sense. I will reimplement related logic.
// ruleTokenCounter record the number of token of value | ||
ruleTokenCounter cache.ConcurrentCounterCache | ||
// goroutineCounter record the number of goroutine of value | ||
goroutineCounter cache.ConcurrentCounterCache |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about concurrencyCounter or something else (as the counter indicates concurrency actually)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make sense
core/freq_params_traffic/rule.go
Outdated
type ControlStrategy int8 | ||
|
||
const ( | ||
RejectFaster ControlStrategy = iota |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just Reject
is enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to express the meaning of quick and direct fail.
”Reject“ may be enough.
core/freq_params_traffic/rule.go
Outdated
|
||
import "strconv" | ||
|
||
type ControlStrategy int8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep the name consistent with that in FlowRule?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's ok. Keep the name convention.
core/freq_params_traffic/rule.go
Outdated
|
||
type SpecificValue struct { | ||
ValType Kind | ||
ValueStr string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep the naming consistent? (both val
or value
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay
core/freq_params_traffic/rule.go
Outdated
QPS | ||
) | ||
|
||
type Kind int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The term "kind" has different meanings in type system. Maybe we could use ParamType
or other concrete name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here i refer to the data type definition of go standard reflect package.
https://github.com/golang/go/blob/98d20fb23551a7ab900fcfe9d25fd9cb6a98a07f/src/reflect/type.go#L230
I think keep name consistent with standard package is ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's okay, but just Kind
may be too generic. Maybe ParamKind
or other concrete?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ParamKind is Okay.
core/freq_params_traffic/slot.go
Outdated
|
||
for _, tc := range tcs { | ||
if tc == nil { | ||
logger.Warnf("Nil traffic controller was found, res: %s", res) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may yield a large number of logs. As this is not expected as usual, maybe we could make it "debug" level?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sense.
core/freq_params_traffic/slot.go
Outdated
logger.Warnf("The TrafficShapingController's paramIndex(%d) less than 0.", idx) | ||
} | ||
if len(args) <= idx { | ||
logger.Warnf("The index of rule is not existed in args. The TrafficShapingController's paramIndex is %d, args: %+v, tc: %+v", idx, args, tc) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto for "debug" level
core/freq_params_traffic/slot.go
Outdated
continue | ||
} | ||
idx := tc.getParamIndex() | ||
if idx < 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could support reversed index here. For example, -1 means the last one. This could be useful when the length of parameter list is not fixed.
awaitTime := expectedTime - currentTimeInMs | ||
if awaitTime > 0 { | ||
atomic.StoreInt64(lastPassTimePtr, expectedTime) | ||
time.Sleep(time.Duration(awaitTime) * time.Millisecond) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's better to use NewTokenResultShouldWait
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay
logger.Warnf("The TrafficShapingController's paramIndex(%d) less than 0.", idx) | ||
} | ||
if len(args) <= idx { | ||
logger.Warnf("The index of rule is not existed in args. The TrafficShapingController's paramIndex is %d, args: %+v, tc: %+v", idx, args, tc) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto for logging level. Also typo: is not existed -> does not exist
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay
3bdd464
to
5fab2ef
Compare
return nil | ||
} | ||
switch arg.(type) { | ||
case int: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also support bool/float32/float64 here?
86ee5dc
to
1974b3e
Compare
Codecov Report
@@ Coverage Diff @@
## master #119 +/- ##
==========================================
+ Coverage 40.77% 42.90% +2.12%
==========================================
Files 68 75 +7
Lines 3279 3951 +672
==========================================
+ Hits 1337 1695 +358
- Misses 1810 2065 +255
- Partials 132 191 +59
Continue to review full report at Codecov.
|
1974b3e
to
aa358bc
Compare
} | ||
|
||
func newBaseTrafficShapingControllerWithMetric(r *Rule, metric *ParamsMetric) *baseTrafficShapingController { | ||
size := int(math.Min(float64(ParamsMaxCapacity), float64(ParamsCapacityBase*r.DurationInSec))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about making the cache size as an attribute of the param flow rule?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe an optional attribute make sense.
I've been testing with the demo and found the pass count flaky like this (see the attachment): sentinel-go-demo-local-metrics.log Rule: {
Resource: "test",
MetricType: freq_params_traffic.QPS,
Behavior: freq_params_traffic.Reject,
ParamIndex: 0,
Threshold: 100,
MaxQueueingTimeMs: 0,
ParamsMaxCapacity: 2,
DurationInSec: 1,
SpecificItems: make(map[freq_params_traffic.SpecificValue]int64),
} Demo: // Usually, the total pass QPS is expected to be 200 (two parameters, 100 respectively).
for i := 0; i < 8; i++ {
go func() {
for {
e, b := sentinel.Entry(Resource, sentinel.WithSlotChain(sc), sentinel.WithArgs(true, rand.Int()%3000, uuid.New().String(), uuid.New().String()))
if b != nil {
// Blocked. We could get the block reason from the BlockError.
time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)
} else {
// Passed, wrap the logic here.
time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)
// Be sure the entry is exited finally.
e.Exit()
}
}
}()
}
for {
e, b := sentinel.Entry(Resource, sentinel.WithSlotChain(sc), sentinel.WithArgs(false, rand.Int()%3000, uuid.New().String(), uuid.New().String()))
if b != nil {
time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)
} else {
// Passed, wrap the logic here.
time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)
// Be sure the entry is exited finally.
e.Exit()
}
} Any ideas about it? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, we may improve this in upcoming pull requests
Fabulous work. Thanks! |
Describe what this PR does / why we need it
Frequency parameters traffic control implementation.
Does this pull request fix one issue?
Describe how you did it
Supporting reject directly strategy and throttling strategy.
Using token counter to record statistics。
Describe how to verify it
Special notes for reviews