-
Notifications
You must be signed in to change notification settings - Fork 910
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
Add ramping up weighted round robin strategy #3217
Conversation
Motivation: Related: line#1757 It will be nice if we have a strategy `EndpointSelectionStrategy` which increases weight gradually for the newly added `Endpoint`s. Modifications: - Add `EndpointSelectionStrategy.rampingUp()` and `builderForRampingUp()` - The strategy increase the weights of newly added `Endpoint`s using `EndpointWeightTransition` - The weight is ramped `totalSteps` times every `rampingUpInterval`. - Endpoints added within the same `updatingTaskWindow` are updated together. Result: - Close line#1757 - You can now use the `EndpointSelectionStrategy` which increases weight gradually for the newly added `Endpoint`s.
Codecov Report
@@ Coverage Diff @@
## master #3217 +/- ##
============================================
- Coverage 74.06% 74.05% -0.01%
- Complexity 13008 13140 +132
============================================
Files 1136 1146 +10
Lines 49276 50025 +749
Branches 6256 6394 +138
============================================
+ Hits 36496 37047 +551
- Misses 9566 9717 +151
- Partials 3214 3261 +47 Continue to review full report at Codecov.
|
core/src/main/java/com/linecorp/armeria/client/endpoint/EndpointSelectionStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/EndpointSelectionStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/EndpointSelectionStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/EndpointWeightTransition.java
Outdated
Show resolved
Hide resolved
...in/java/com/linecorp/armeria/client/endpoint/RampingUpWeightedRoundRobinStrategyBuilder.java
Outdated
Show resolved
Hide resolved
...in/java/com/linecorp/armeria/client/endpoint/RampingUpWeightedRoundRobinStrategyBuilder.java
Outdated
Show resolved
Hide resolved
...in/java/com/linecorp/armeria/client/endpoint/RampingUpWeightedRoundRobinStrategyBuilder.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightBasedRandomEndpointSelector.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightBasedRandomEndpointSelector.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightBasedRandomEndpointSelector.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightBasedRandomEndpointSelector.java
Outdated
Show resolved
Hide resolved
return null; | ||
} | ||
|
||
private void removeEntry(Entry entry) { |
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.
By the way, why does this class have the ability to remove entries but not add them? Seems assymetrical.
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.
Yeah, this is an asymmetric algorithm. 😉
Each entry is removed from currentEntries
when the counter of each endpoint reached the weight.
And the removed entries are added back to the currentEntries
when all entries are removed.
This guarantees that the endpoint whose weight is very low is always selected when selectEndpoint()
is called by totalWeight
times.
...in/java/com/linecorp/armeria/client/endpoint/RampingUpWeightedRoundRobinStrategyBuilder.java
Outdated
Show resolved
Hide resolved
.../src/main/java/com/linecorp/armeria/client/endpoint/RampingUpWeightedRoundRobinStrategy.java
Outdated
Show resolved
Hide resolved
.../src/main/java/com/linecorp/armeria/client/endpoint/RampingUpWeightedRoundRobinStrategy.java
Outdated
Show resolved
Hide resolved
.../src/main/java/com/linecorp/armeria/client/endpoint/RampingUpWeightedRoundRobinStrategy.java
Outdated
Show resolved
Hide resolved
.../src/main/java/com/linecorp/armeria/client/endpoint/RampingUpWeightedRoundRobinStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightBasedRandomEndpointSelector.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightBasedRandomEndpointSelector.java
Outdated
Show resolved
Hide resolved
.../src/main/java/com/linecorp/armeria/client/endpoint/RampingUpWeightedRoundRobinStrategy.java
Outdated
Show resolved
Hide resolved
.../src/main/java/com/linecorp/armeria/client/endpoint/RampingUpWeightedRoundRobinStrategy.java
Outdated
Show resolved
Hide resolved
.../src/main/java/com/linecorp/armeria/client/endpoint/RampingUpWeightedRoundRobinStrategy.java
Outdated
Show resolved
Hide resolved
} | ||
|
||
// The entry is full so we should remove the entry from currentEntries. | ||
synchronized (currentEntries) { |
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.
Just wondering, is the removal easier to reason about than making entries as unavailable? Something like this? Not sure if this works exactly but something along these lines
if (!entry.isFull()) {
return selected;
} else if (entry.isUnavailable()) {
continue;
}
entry.markUnavailable();
currentTotalWeight.decrementAndGet(entry.endpoint().weight());
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.
Hm, if we don't remove the entry, isn't there chances that the endpoint with low weight (e.g. 1) is not selected even after one turn(totalWeigth) is passed?
We use a random number to select an endpoint so removing entries will guarantee that the endpoint is selected evenly with its weight. 🤔
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.
Well I figured an unavailable marker should be equivalent to removal, just without having to manage the list and maybe easier to mutate it atomically. if (unavailable) continue;
feels equivalent semantically to removal. But maybe missing some corner case.
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 now realized the logic I implemented was not working as I expected. 😅 Maybe that's the reason that I got confused.
The current logic is slanted because the entry, which is next to the endpoint whose weight is large, will get much chance to get selected after the endpoint is full.
So I have to recalculate the lowerBound
after the entry is removed but I forgot about it. 😅
On the other hand, I'm a bit doubtful about recalculation. Let me think about this. 🤔
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.
@anuraaga I updated the logic a bit. PTAL. 🙇♂️
.../src/main/java/com/linecorp/armeria/client/endpoint/RampingUpWeightedRoundRobinStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/EndpointSelectionStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/EndpointWeightTransition.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightBasedRandomEndpointSelector.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightBasedRandomEndpointSelector.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightBasedRandomEndpointSelector.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightBasedRandomEndpointSelector.java
Outdated
Show resolved
Hide resolved
.../src/main/java/com/linecorp/armeria/client/endpoint/RampingUpWeightedRoundRobinStrategy.java
Outdated
Show resolved
Hide resolved
.../src/main/java/com/linecorp/armeria/client/endpoint/RampingUpWeightedRoundRobinStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategyBuilder.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategyBuilder.java
Outdated
Show resolved
Hide resolved
...in/java/com/linecorp/armeria/client/endpoint/WeightedRandomDistributionEndpointSelector.java
Outdated
Show resolved
Hide resolved
...in/java/com/linecorp/armeria/client/endpoint/WeightedRandomDistributionEndpointSelector.java
Outdated
Show resolved
Hide resolved
...in/java/com/linecorp/armeria/client/endpoint/WeightedRandomDistributionEndpointSelector.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategy.java
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategy.java
Outdated
Show resolved
Hide resolved
...in/java/com/linecorp/armeria/client/endpoint/WeightedRandomDistributionEndpointSelector.java
Outdated
Show resolved
Hide resolved
tomcat8/tomcat.8080/work/Tomcat/localhost/ROOT/org/apache/jsp/index_jsp.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategyBuilder.java
Outdated
Show resolved
Hide resolved
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.
Left some possible javadoc suggestions
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategyBuilder.java
Outdated
Show resolved
Hide resolved
} | ||
|
||
/** | ||
* Sets the specified {@link ScheduledExecutorService} that will be used to compute the weight of |
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.
Sets the ScheduledExecutorService to use to execute tasks for computing new weights.
By the way is it safe for this to be multi threaded or should it accept a netty type 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.
Oh, it should be single-threaded. Let me use EventExecutor
. Thanks!
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategyBuilder.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategyBuilder.java
Outdated
Show resolved
Hide resolved
* until the number of ramping reaches to the {@code totalSteps}. | ||
* {@value DEFAULT_NUMBER_OF_STEPS} is used by default. | ||
*/ | ||
public WeightRampingUpStrategyBuilder totalSteps(int totalSteps) { |
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.
numberSteps maybe better, its not so much a total.
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 a good suggestion. 👍
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategyBuilder.java
Outdated
Show resolved
Hide resolved
All fixed. PTAL. 😉 |
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategyBuilder.java
Outdated
Show resolved
Hide resolved
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.
Left some minor nits.
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategy.java
Outdated
Show resolved
Hide resolved
...in/java/com/linecorp/armeria/client/endpoint/WeightedRandomDistributionEndpointSelector.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategy.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/client/endpoint/WeightRampingUpStrategy.java
Outdated
Show resolved
Hide resolved
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.
Many users have been waiting for this feature. You made 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.
Shall we add @UnstableApi
to all new public classes and methods, just in case we'll have to update the API?
core/src/main/java/com/linecorp/armeria/client/endpoint/EndpointSelectionStrategy.java
Outdated
Show resolved
Hide resolved
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.
Thanks a lot for your patience, @minwoox 🙇
🎉🎉🎉 |
Thanks!!!!!! 🎉🎉🎉 |
Thanks a lot, reviewers! |
Motivation:
Related: #1757
It will be nice if we have a strategy
EndpointSelectionStrategy
which increases weight graduallyfor the newly added
Endpoint
s.Modifications:
EndpointSelectionStrategy.rampingUp()
andbuilderForRampingUp()
Endpoint
s usingEndpointWeightTransition
totalSteps
times everyrampingUpInterval
.updatingTaskWindow
are updated together.Result:
EndpointSelectionStrategy
which increases weight gradually #1757EndpointSelectionStrategy
which increases weight graduallyfor the newly added
Endpoint
s.