Skip to content

Commit 29bf324

Browse files
committed
Pass address weights to wrr balancer through attributes.
1 parent 8e6052a commit 29bf324

File tree

4 files changed

+116
-5
lines changed

4 files changed

+116
-5
lines changed

attributes/attributes.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ func New(kvs ...interface{}) *Attributes {
5050
// times, the last value overwrites all previous values for that key. To
5151
// remove an existing key, use a nil value.
5252
func (a *Attributes) WithValues(kvs ...interface{}) *Attributes {
53+
if a == nil {
54+
a = New()
55+
}
5356
if len(kvs)%2 != 0 {
5457
panic(fmt.Sprintf("attributes.New called with unexpected input: len(kvs) = %v", len(kvs)))
5558
}

balancer/weightedroundrobin/weightedroundrobin.go

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,41 @@
1919
// Package weightedroundrobin defines a weighted roundrobin balancer.
2020
package weightedroundrobin
2121

22-
// Name is the name of weighted_round_robin balancer.
23-
const Name = "weighted_round_robin"
22+
import "google.golang.org/grpc/attributes"
23+
24+
const (
25+
// Name is the name of weighted_round_robin balancer.
26+
Name = "weighted_round_robin"
27+
28+
// Attribute key used to store AddrInfo in the Attributes field of
29+
// resolver.Address.
30+
attributeKey = "/balancer/weightedroundrobin/addrInfo"
31+
)
2432

2533
// AddrInfo will be stored inside Address metadata in order to use weighted roundrobin
2634
// balancer.
2735
type AddrInfo struct {
2836
Weight uint32
2937
}
38+
39+
// AddAddrInfoToAttributes returns a new Attributes containing all key/value
40+
// pairs in a with ai being added to it.
41+
func AddAddrInfoToAttributes(ai *AddrInfo, a *attributes.Attributes) *attributes.Attributes {
42+
return a.WithValues(attributeKey, ai)
43+
}
44+
45+
// GetAddrInfoFromAttributes returns the AddrInfo stored in a. Returns nil if no
46+
// AddrInfo is present in a.
47+
func GetAddrInfoFromAttributes(a *attributes.Attributes) *AddrInfo {
48+
if a == nil {
49+
return nil
50+
}
51+
ai := a.Value(attributeKey)
52+
if ai == nil {
53+
return nil
54+
}
55+
if _, ok := ai.(*AddrInfo); !ok {
56+
return nil
57+
}
58+
return ai.(*AddrInfo)
59+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
*
3+
* Copyright 2020 gRPC authors.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package weightedroundrobin
20+
21+
import (
22+
"testing"
23+
24+
"github.com/google/go-cmp/cmp"
25+
26+
"google.golang.org/grpc/attributes"
27+
)
28+
29+
func TestAddAddrInfoToAndFromAttributes(t *testing.T) {
30+
tests := []struct {
31+
desc string
32+
inputAddrInfo *AddrInfo
33+
inputAttributes *attributes.Attributes
34+
wantAddrInfo *AddrInfo
35+
}{
36+
{
37+
desc: "empty attributes",
38+
inputAddrInfo: &AddrInfo{Weight: 100},
39+
inputAttributes: nil,
40+
wantAddrInfo: &AddrInfo{Weight: 100},
41+
},
42+
{
43+
desc: "non-empty attributes",
44+
inputAddrInfo: &AddrInfo{Weight: 100},
45+
inputAttributes: attributes.New("foo", "bar"),
46+
wantAddrInfo: &AddrInfo{Weight: 100},
47+
},
48+
{
49+
desc: "addrInfo not present in empty attributes",
50+
inputAddrInfo: nil,
51+
inputAttributes: nil,
52+
wantAddrInfo: nil,
53+
},
54+
{
55+
desc: "addrInfo not present in non-empty attributes",
56+
inputAddrInfo: nil,
57+
inputAttributes: attributes.New("foo", "bar"),
58+
wantAddrInfo: nil,
59+
},
60+
}
61+
62+
for _, test := range tests {
63+
t.Run(test.desc, func(t *testing.T) {
64+
outputAttributes := AddAddrInfoToAttributes(test.inputAddrInfo, test.inputAttributes)
65+
gotAddrInfo := GetAddrInfoFromAttributes(outputAttributes)
66+
if !cmp.Equal(gotAddrInfo, test.wantAddrInfo) {
67+
t.Errorf("gotAddrInfo: %v, wantAddrInfo: %v", gotAddrInfo, test.wantAddrInfo)
68+
}
69+
70+
})
71+
}
72+
}

xds/internal/balancer/edsbalancer/eds_impl.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,15 @@ func (edsImpl *edsBalancerImpl) handleEDSResponsePerPriority(bgwc *balancerGroup
277277
Addr: lbEndpoint.Address,
278278
}
279279
if edsImpl.subBalancerBuilder.Name() == weightedroundrobin.Name && lbEndpoint.Weight != 0 {
280-
address.Metadata = &weightedroundrobin.AddrInfo{
281-
Weight: lbEndpoint.Weight,
282-
}
280+
ai := &weightedroundrobin.AddrInfo{Weight: lbEndpoint.Weight}
281+
address.Attributes = weightedroundrobin.AddAddrInfoToAttributes(ai, address.Attributes)
282+
// Metadata field in resolver.Address is deprecated. The
283+
// attributes field should be used to specify arbitrary
284+
// attributes about the address. We still need to populate the
285+
// Metadata field here to allow users of this field to migrate
286+
// to the new one.
287+
// TODO(easwars): Remove this once all users have migrated.
288+
address.Metadata = ai
283289
}
284290
newAddrs = append(newAddrs, address)
285291
}

0 commit comments

Comments
 (0)