You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by xu...@apache.org on 2026/06/14 06:12:06 UTC

(dubbo-go) branch develop updated: feat(loadbalance): introduce GetWeightAt for consistent weight calculation using Unix timestamp (#3410)

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 <ha...@gmail.com>
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 <ha...@gmail.com>
---
 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)