Commit ccc6e0cf authored by Miek Gieben's avatar Miek Gieben

Use weights from xDS

use the weights as reported. Set prio to 0 to signal it's not used.
Signed-off-by: default avatarMiek Gieben <miek@miek.nl>
parent 6afcfb83
...@@ -108,7 +108,7 @@ For SRV queries all endpoints are returned, the SRV target names are synthesized ...@@ -108,7 +108,7 @@ For SRV queries all endpoints are returned, the SRV target names are synthesized
## Matching Algorithm ## Matching Algorithm
How are clients match against the data we receive from xDS endpoint? How are queries match against the data we receive from xDS endpoint?
1. Does the cluster exist? If not return NXDOMAIN, otherwise continue. 1. Does the cluster exist? If not return NXDOMAIN, otherwise continue.
...@@ -116,7 +116,9 @@ How are clients match against the data we receive from xDS endpoint? ...@@ -116,7 +116,9 @@ How are clients match against the data we receive from xDS endpoint?
endpoint return a NODATA response, otherwise continue. endpoint return a NODATA response, otherwise continue.
3. If weights are assigned, use those to pick an endpoint, otherwise randomly pick one and return a 3. If weights are assigned, use those to pick an endpoint, otherwise randomly pick one and return a
response to the client. response to the client. Weights are copied from the xDS data, priority is not used and set to 0
for all SRV records. Note that weights in SRV records are 16 bits, but xDS uses uint32; you have
been warned.
## Metrics ## Metrics
......
...@@ -103,7 +103,7 @@ func (t *Traffic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg ...@@ -103,7 +103,7 @@ func (t *Traffic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
} }
m.Answer = []dns.RR{&dns.AAAA{Hdr: dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 5}, AAAA: sockaddr.Address()}} m.Answer = []dns.RR{&dns.AAAA{Hdr: dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 5}, AAAA: sockaddr.Address()}}
case dns.TypeSRV: case dns.TypeSRV:
sockaddrs, _ := t.c.All(cluster, true) sockaddrs, weights, _ := t.c.All(cluster, true)
m.Answer = make([]dns.RR, 0, len(sockaddrs)) m.Answer = make([]dns.RR, 0, len(sockaddrs))
m.Extra = make([]dns.RR, 0, len(sockaddrs)) m.Extra = make([]dns.RR, 0, len(sockaddrs))
for i, sa := range sockaddrs { for i, sa := range sockaddrs {
...@@ -111,7 +111,7 @@ func (t *Traffic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg ...@@ -111,7 +111,7 @@ func (t *Traffic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
m.Answer = append(m.Answer, &dns.SRV{ m.Answer = append(m.Answer, &dns.SRV{
Hdr: dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeSRV, Class: dns.ClassINET, Ttl: 5}, Hdr: dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeSRV, Class: dns.ClassINET, Ttl: 5},
Priority: 100, Weight: 100, Port: sa.Port(), Target: target}) Priority: 0, Weight: uint16(weights[i]), Port: sa.Port(), Target: target})
if sa.Address().To4() == nil { if sa.Address().To4() == nil {
m.Extra = append(m.Extra, &dns.AAAA{Hdr: dns.RR_Header{Name: target, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 5}, AAAA: sa.Address()}) m.Extra = append(m.Extra, &dns.AAAA{Hdr: dns.RR_Header{Name: target, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 5}, AAAA: sa.Address()})
...@@ -120,7 +120,7 @@ func (t *Traffic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg ...@@ -120,7 +120,7 @@ func (t *Traffic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
} }
} }
case dns.TypeTXT: case dns.TypeTXT:
sockaddrs, _ := t.c.All(cluster, false) sockaddrs, weights, _ := t.c.All(cluster, false)
m.Answer = make([]dns.RR, 0, len(sockaddrs)) m.Answer = make([]dns.RR, 0, len(sockaddrs))
m.Extra = make([]dns.RR, 0, len(sockaddrs)) m.Extra = make([]dns.RR, 0, len(sockaddrs))
for i, sa := range sockaddrs { for i, sa := range sockaddrs {
...@@ -128,7 +128,7 @@ func (t *Traffic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg ...@@ -128,7 +128,7 @@ func (t *Traffic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
m.Answer = append(m.Answer, &dns.TXT{ m.Answer = append(m.Answer, &dns.TXT{
Hdr: dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 5}, Hdr: dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 5},
Txt: []string{"100", "100", strconv.Itoa(int(sa.Port())), target, corepb2.HealthStatus_name[int32(sa.Health)]}}) Txt: []string{"0", strconv.Itoa(int(uint16(weights[i]))), strconv.Itoa(int(sa.Port())), target, corepb2.HealthStatus_name[int32(sa.Health)]}})
m.Extra = append(m.Extra, &dns.TXT{Hdr: dns.RR_Header{Name: target, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 5}, Txt: []string{sa.Address().String()}}) m.Extra = append(m.Extra, &dns.TXT{Hdr: dns.RR_Header{Name: target, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 5}, Txt: []string{sa.Address().String()}})
} }
default: default:
...@@ -162,7 +162,7 @@ func (t *Traffic) serveEndpoint(ctx context.Context, state request.Request, endp ...@@ -162,7 +162,7 @@ func (t *Traffic) serveEndpoint(ctx context.Context, state request.Request, endp
return 0, nil return 0, nil
} }
sockaddrs, _ := t.c.All(cluster, healthy) sockaddrs, _, _ := t.c.All(cluster, healthy)
if len(sockaddrs) < nr { if len(sockaddrs) < nr {
m.Ns = soa(state.Zone) m.Ns = soa(state.Zone)
m.Rcode = dns.RcodeNameError m.Rcode = dns.RcodeNameError
......
...@@ -126,21 +126,27 @@ func (a *assignment) Select(cluster string, healthy bool) (*SocketAddress, bool) ...@@ -126,21 +126,27 @@ func (a *assignment) Select(cluster string, healthy bool) (*SocketAddress, bool)
return nil, true return nil, true
} }
// All returns all healthy endpoints. // All returns all healthy endpoints, together with their weights.
func (a *assignment) All(cluster string, healthy bool) ([]*SocketAddress, bool) { func (a *assignment) All(cluster string, healthy bool) ([]*SocketAddress, []uint32, bool) {
cla := a.ClusterLoadAssignment(cluster) cla := a.ClusterLoadAssignment(cluster)
if cla == nil { if cla == nil {
return nil, false return nil, nil, false
} }
sa := []*SocketAddress{} sa := []*SocketAddress{}
we := []uint32{}
for _, ep := range cla.Endpoints { for _, ep := range cla.Endpoints {
for _, lb := range ep.GetLbEndpoints() { for _, lb := range ep.GetLbEndpoints() {
if healthy && lb.GetHealthStatus() != corepb2.HealthStatus_HEALTHY { if healthy && lb.GetHealthStatus() != corepb2.HealthStatus_HEALTHY {
continue continue
} }
weight := lb.GetLoadBalancingWeight().GetValue()
if weight > 2^16 {
log.Warning("Weight in cluster %q > %d, truncating to %d in SRV responses", cluster, weight, uint16(weight))
}
we = append(we, weight)
sa = append(sa, &SocketAddress{lb.GetEndpoint().GetAddress().GetSocketAddress(), lb.GetHealthStatus()}) sa = append(sa, &SocketAddress{lb.GetEndpoint().GetAddress().GetSocketAddress(), lb.GetHealthStatus()})
} }
} }
return sa, true return sa, we, true
} }
...@@ -205,9 +205,9 @@ func (c *Client) Select(cluster string, healty bool) (*SocketAddress, bool) { ...@@ -205,9 +205,9 @@ func (c *Client) Select(cluster string, healty bool) (*SocketAddress, bool) {
} }
// All returns all endpoints. // All returns all endpoints.
func (c *Client) All(cluster string, healty bool) ([]*SocketAddress, bool) { func (c *Client) All(cluster string, healty bool) ([]*SocketAddress, []uint32, bool) {
if cluster == "" { if cluster == "" {
return nil, false return nil, nil, false
} }
return c.assignments.All(cluster, healty) return c.assignments.All(cluster, healty)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment