This is an automated email from the ASF dual-hosted git repository.
Alanxtl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git
The following commit(s) were added to refs/heads/develop by this push:
new bd1c9f1ea feat(loadbalance): introduce GetWeightAt for consistent
weight calculation using Unix timestamp (#3410)
bd1c9f1ea is described below
commit bd1c9f1ea11ebb60e407aba4678a459f4b691d4e
Author: Harsh Mehta <[email protected]>
AuthorDate: Sun Jun 14 11:42:01 2026 +0530
feat(loadbalance): introduce GetWeightAt for consistent weight calculation
using Unix timestamp (#3410)
Signed-off-by: Harsh Mehta <[email protected]>
---
cluster/loadbalance/aliasmethod/alias_method.go | 4 +++-
cluster/loadbalance/iwrr/iwrr.go | 4 +++-
cluster/loadbalance/leastactive/loadbalance.go | 4 +++-
cluster/loadbalance/loadbalance_benchmarks_test.go | 22 ++++++++++++++++++++++
cluster/loadbalance/random/loadbalance.go | 4 +++-
cluster/loadbalance/roundrobin/loadbalance.go | 3 ++-
cluster/loadbalance/util.go | 8 +++++++-
7 files changed, 43 insertions(+), 6 deletions(-)
diff --git a/cluster/loadbalance/aliasmethod/alias_method.go
b/cluster/loadbalance/aliasmethod/alias_method.go
index dbbe93b06..cba727af1 100644
--- a/cluster/loadbalance/aliasmethod/alias_method.go
+++ b/cluster/loadbalance/aliasmethod/alias_method.go
@@ -20,6 +20,7 @@ package aliasmethod // weighted random with alias-method
algorithm
import (
"math/rand"
+ "time"
)
import (
@@ -56,8 +57,9 @@ func (am *aliasMethodPicker) init(invocation base.Invocation)
{
small := make([]int, 0, n)
large := make([]int, 0, n)
+ now := time.Now().Unix()
for i, invoker := range am.invokers {
- weight := loadbalance.GetWeight(invoker, invocation)
+ weight := loadbalance.GetWeightAt(invoker, invocation, now)
weights[i] = weight
totalWeight += weight
}
diff --git a/cluster/loadbalance/iwrr/iwrr.go b/cluster/loadbalance/iwrr/iwrr.go
index 938e77db7..b17dc136b 100644
--- a/cluster/loadbalance/iwrr/iwrr.go
+++ b/cluster/loadbalance/iwrr/iwrr.go
@@ -20,6 +20,7 @@ package iwrr
import (
"math/rand"
"sync"
+ "time"
)
import (
@@ -85,9 +86,10 @@ func NewInterleavedweightedRoundRobin(invokers
[]base.Invoker, invocation base.I
size := uint64(len(invokers))
offset := rand.Uint64() % size //NOSONAR
step := int64(0)
+ now := time.Now().Unix()
for idx := uint64(0); idx < size; idx++ {
invoker := invokers[(idx+offset)%size]
- weight := loadbalance.GetWeight(invoker, invocation)
+ weight := loadbalance.GetWeightAt(invoker, invocation, now)
step = gcdInt(step, weight)
iwrrp.current.push(&iwrrEntry{
invoker: invoker,
diff --git a/cluster/loadbalance/leastactive/loadbalance.go
b/cluster/loadbalance/leastactive/loadbalance.go
index 26c1237f0..27c8f7f52 100644
--- a/cluster/loadbalance/leastactive/loadbalance.go
+++ b/cluster/loadbalance/leastactive/loadbalance.go
@@ -19,6 +19,7 @@ package leastactive
import (
"math/rand"
+ "time"
)
import (
@@ -66,12 +67,13 @@ func (lb *leastActiveLoadBalance) Select(invokers
[]base.Invoker, invocation bas
weights = make([]int64, count) // The weight of every
invokers
)
+ now := time.Now().Unix()
for i := 0; i < count; i++ {
invoker := invokers[i]
// Active number
active := base.GetMethodStatus(invoker.GetURL(),
invocation.MethodName()).GetActive()
// current weight (maybe in warmUp)
- afterWarmup := loadbalance.GetWeight(invoker, invocation)
+ afterWarmup := loadbalance.GetWeightAt(invoker, invocation, now)
// save for later use
weights[i] = afterWarmup
// There are smaller active services
diff --git a/cluster/loadbalance/loadbalance_benchmarks_test.go
b/cluster/loadbalance/loadbalance_benchmarks_test.go
index c8adbf7ef..f8a483895 100644
--- a/cluster/loadbalance/loadbalance_benchmarks_test.go
+++ b/cluster/loadbalance/loadbalance_benchmarks_test.go
@@ -20,6 +20,7 @@ package loadbalance_test
import (
"fmt"
"testing"
+ "time"
)
import (
@@ -84,3 +85,24 @@ func BenchmarkRandomLoadbalance(b *testing.B) {
func BenchmarkAliasMethodLoadbalance(b *testing.B) {
Benchloadbalance(b,
extension.GetLoadbalance(constant.LoadBalanceKeyAliasMethod))
}
+
+func BenchmarkGetWeight(b *testing.B) {
+ invokers := Generate()
+ inv := &invocation.RPCInvocation{}
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ loadbalance.GetWeight(invokers[i%len(invokers)], inv)
+ }
+}
+
+func BenchmarkGetWeightAt(b *testing.B) {
+ invokers := Generate()
+ inv := &invocation.RPCInvocation{}
+ now := time.Now().Unix()
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ loadbalance.GetWeightAt(invokers[i%len(invokers)], inv, now)
+ }
+}
diff --git a/cluster/loadbalance/random/loadbalance.go
b/cluster/loadbalance/random/loadbalance.go
index 296579398..43ce7ee81 100644
--- a/cluster/loadbalance/random/loadbalance.go
+++ b/cluster/loadbalance/random/loadbalance.go
@@ -19,6 +19,7 @@ package random
import (
"math/rand"
+ "time"
)
import (
@@ -56,8 +57,9 @@ func (lb *randomLoadBalance) Select(invokers []base.Invoker,
invocation base.Inv
// The sum of weights
var totalWeight int64 = 0
+ now := time.Now().Unix()
for i := 0; i < length; i++ {
- weight := loadbalance.GetWeight(invokers[i], invocation)
+ weight := loadbalance.GetWeightAt(invokers[i], invocation, now)
//Sum
totalWeight += weight
// save for later use
diff --git a/cluster/loadbalance/roundrobin/loadbalance.go
b/cluster/loadbalance/roundrobin/loadbalance.go
index ce5284560..3530968b4 100644
--- a/cluster/loadbalance/roundrobin/loadbalance.go
+++ b/cluster/loadbalance/roundrobin/loadbalance.go
@@ -74,12 +74,13 @@ func (lb *rrLoadBalance) Select(invokers []base.Invoker,
invocation base.Invocat
totalWeight = int64(0)
maxCurrentWeight = int64(math.MinInt64)
now = time.Now()
+ nowUnix = now.Unix()
selectedInvoker base.Invoker
selectedWeightRobin *weightedRoundRobin
)
for _, invoker := range invokers {
- weight := max(loadbalance.GetWeight(invoker, invocation), 0)
+ weight := max(loadbalance.GetWeightAt(invoker, invocation,
nowUnix), 0)
identifier := invoker.GetURL().Key()
wr := &weightedRoundRobin{weight: weight}
diff --git a/cluster/loadbalance/util.go b/cluster/loadbalance/util.go
index d31d8f2e5..83e10375c 100644
--- a/cluster/loadbalance/util.go
+++ b/cluster/loadbalance/util.go
@@ -28,7 +28,14 @@ import (
// GetWeight returns the weight for the load‑balancing strategy.
func GetWeight(invoker base.Invoker, invocation base.Invocation) int64 {
+ return GetWeightAt(invoker, invocation, time.Now().Unix())
+}
+// GetWeightAt returns the weight for the load-balancing strategy using the
+// provided Unix timestamp. Callers that loop over many invokers should compute
+// now once and pass it here to avoid repeated time.Now() calls and to keep the
+// warmup calculation consistent within a single selection.
+func GetWeightAt(invoker base.Invoker, invocation base.Invocation, now int64)
int64 {
url := invoker.GetURL()
// Method‑level or registry‑level weight taken from URL parameters —
highest priority.
@@ -46,7 +53,6 @@ func GetWeight(invoker base.Invoker, invocation
base.Invocation) int64 {
// Warm‑up adjustment (same logic as before).
if weight > 0 {
- now := time.Now().Unix()
ts := url.GetParamInt(constant.RemoteTimestampKey, now)
if uptime := now - ts; uptime > 0 {
warm := url.GetParamInt(constant.WarmupKey,
constant.DefaultWarmup)