@@ -22,6 +22,7 @@ import (
2222 "errors"
2323 "fmt"
2424
25+ "google.golang.org/grpc/attributes"
2526 "google.golang.org/grpc/balancer"
2627 "google.golang.org/grpc/connectivity"
2728 "google.golang.org/grpc/grpclog"
@@ -41,7 +42,7 @@ func (bb *baseBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions)
4142 cc : cc ,
4243 pickerBuilder : bb .pickerBuilder ,
4344
44- subConns : make (map [resolver.Address ]balancer. SubConn ),
45+ subConns : make (map [resolver.Address ]subConnInfo ),
4546 scStates : make (map [balancer.SubConn ]connectivity.State ),
4647 csEvltr : & balancer.ConnectivityStateEvaluator {},
4748 config : bb .config ,
@@ -57,14 +58,19 @@ func (bb *baseBuilder) Name() string {
5758 return bb .name
5859}
5960
61+ type subConnInfo struct {
62+ subConn balancer.SubConn
63+ attrs * attributes.Attributes
64+ }
65+
6066type baseBalancer struct {
6167 cc balancer.ClientConn
6268 pickerBuilder PickerBuilder
6369
6470 csEvltr * balancer.ConnectivityStateEvaluator
6571 state connectivity.State
6672
67- subConns map [resolver.Address ]balancer. SubConn // `attributes` is stripped from the keys of this map (the addresses)
73+ subConns map [resolver.Address ]subConnInfo // `attributes` is stripped from the keys of this map (the addresses)
6874 scStates map [balancer.SubConn ]connectivity.State
6975 picker balancer.Picker
7076 config Config
@@ -114,7 +120,7 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
114120 aNoAttrs := a
115121 aNoAttrs .Attributes = nil
116122 addrsSet [aNoAttrs ] = struct {}{}
117- if sc , ok := b .subConns [aNoAttrs ]; ! ok {
123+ if scInfo , ok := b .subConns [aNoAttrs ]; ! ok {
118124 // a is a new address (not existing in b.subConns).
119125 //
120126 // When creating SubConn, the original address with attributes is
@@ -125,7 +131,7 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
125131 logger .Warningf ("base.baseBalancer: failed to create new SubConn: %v" , err )
126132 continue
127133 }
128- b .subConns [aNoAttrs ] = sc
134+ b .subConns [aNoAttrs ] = subConnInfo { subConn : sc , attrs : a . Attributes }
129135 b .scStates [sc ] = connectivity .Idle
130136 sc .Connect ()
131137 } else {
@@ -135,13 +141,15 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
135141 // The SubConn does a reflect.DeepEqual of the new and old
136142 // addresses. So this is a noop if the current address is the same
137143 // as the old one (including attributes).
138- b .cc .UpdateAddresses (sc , []resolver.Address {a })
144+ scInfo .attrs = a .Attributes
145+ b .subConns [aNoAttrs ] = scInfo
146+ b .cc .UpdateAddresses (scInfo .subConn , []resolver.Address {a })
139147 }
140148 }
141- for a , sc := range b .subConns {
149+ for a , scInfo := range b .subConns {
142150 // a was removed by resolver.
143151 if _ , ok := addrsSet [a ]; ! ok {
144- b .cc .RemoveSubConn (sc )
152+ b .cc .RemoveSubConn (scInfo . subConn )
145153 delete (b .subConns , a )
146154 // Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
147155 // The entry will be deleted in UpdateSubConnState.
@@ -184,9 +192,10 @@ func (b *baseBalancer) regeneratePicker() {
184192 readySCs := make (map [balancer.SubConn ]SubConnInfo )
185193
186194 // Filter out all ready SCs from full subConn map.
187- for addr , sc := range b .subConns {
188- if st , ok := b .scStates [sc ]; ok && st == connectivity .Ready {
189- readySCs [sc ] = SubConnInfo {Address : addr }
195+ for addr , scInfo := range b .subConns {
196+ if st , ok := b .scStates [scInfo .subConn ]; ok && st == connectivity .Ready {
197+ addr .Attributes = scInfo .attrs
198+ readySCs [scInfo .subConn ] = SubConnInfo {Address : addr }
190199 }
191200 }
192201 b .picker = b .pickerBuilder .Build (PickerBuildInfo {ReadySCs : readySCs })
0 commit comments