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)

Reply via email to