Perform a binary search to find optimal size of DNS responses
Will fix https://github.com/hashicorp/consul/issues/4036 Instead of removing one by one the entries, find the optimal size using binary search. For SRV records, with 5k nodes, duration of DNS lookups is divided by 4 or more.
This commit is contained in:
parent
4df67b15e9
commit
9a819b5b29
42
agent/dns.go
42
agent/dns.go
|
@ -717,6 +717,32 @@ func syncExtra(index map[string]dns.RR, resp *dns.Msg) {
|
|||
resp.Extra = extra
|
||||
}
|
||||
|
||||
func dnsBinaryTruncate(resp *dns.Msg, maxSize int, index map[string]dns.RR, hasExtra bool) int {
|
||||
originalAnswser := resp.Answer
|
||||
startIndex := 0
|
||||
endIndex := len(resp.Answer)
|
||||
for endIndex-startIndex > 1 {
|
||||
median := startIndex + (endIndex-startIndex)/2
|
||||
|
||||
resp.Answer = originalAnswser[:median]
|
||||
resp.Extra = originalAnswser[:median]
|
||||
if hasExtra {
|
||||
syncExtra(index, resp)
|
||||
}
|
||||
aLen := resp.Len()
|
||||
if aLen <= maxSize {
|
||||
if maxSize-aLen < 10 {
|
||||
// We are good, increasing will go out of bounds
|
||||
return median
|
||||
}
|
||||
startIndex = median
|
||||
} else {
|
||||
endIndex = median
|
||||
}
|
||||
}
|
||||
return startIndex
|
||||
}
|
||||
|
||||
// trimTCPResponse limit the MaximumSize of messages to 64k as it is the limit
|
||||
// of DNS responses
|
||||
func (d *DNSServer) trimTCPResponse(req, resp *dns.Msg) (trimmed bool) {
|
||||
|
@ -752,7 +778,13 @@ func (d *DNSServer) trimTCPResponse(req, resp *dns.Msg) (trimmed bool) {
|
|||
// This enforces the given limit on 64k, the max limit for DNS messages
|
||||
for len(resp.Answer) > 0 && resp.Len() > maxSize {
|
||||
truncated = true
|
||||
resp.Answer = resp.Answer[:len(resp.Answer)-1]
|
||||
// More than 100 bytes, find with a binary search
|
||||
if resp.Len()-maxSize > 100 {
|
||||
bestIndex := dnsBinaryTruncate(resp, maxSize, index, hasExtra)
|
||||
resp.Answer = resp.Answer[:bestIndex]
|
||||
} else {
|
||||
resp.Answer = resp.Answer[:len(resp.Answer)-1]
|
||||
}
|
||||
if hasExtra {
|
||||
syncExtra(index, resp)
|
||||
}
|
||||
|
@ -809,7 +841,13 @@ func trimUDPResponse(req, resp *dns.Msg, udpAnswerLimit int) (trimmed bool) {
|
|||
compress := resp.Compress
|
||||
resp.Compress = false
|
||||
for len(resp.Answer) > 0 && resp.Len() > maxSize {
|
||||
resp.Answer = resp.Answer[:len(resp.Answer)-1]
|
||||
// More than 100 bytes, find with a binary search
|
||||
if resp.Len()-maxSize > 100 {
|
||||
bestIndex := dnsBinaryTruncate(resp, maxSize, index, hasExtra)
|
||||
resp.Answer = resp.Answer[:bestIndex]
|
||||
} else {
|
||||
resp.Answer = resp.Answer[:len(resp.Answer)-1]
|
||||
}
|
||||
if hasExtra {
|
||||
syncExtra(index, resp)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue