-
Notifications
You must be signed in to change notification settings - Fork 673
Conversation
Could this be changed in a separate PR, to make things more incremental? |
@squaremo It could be done, but that would require some surgery in the |
@squaremo I have reverted the changes in the server, so it uses the old mechanism + the cache... |
Thanks @inercia, I'll take another look |
} | ||
|
||
// set the reply for the entry | ||
func (e *cacheEntry) setReply(reply *dns.Msg, flags uint8, now time.Time) { |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
Surely we need to significantly lower the default ttl in dns.go...
See the discussion in #225. IMO anything higher than 30s is going to be problematic in a fair number of situations. I suggest we make that the default, with a facility to override the value via an option to Incidentally, if this PR closes #225, then a separate PR needs to be opened to address the scalability issues identified in #225. |
I agree, I will reduce the I will open a new PR later on for the scalability issues you described... |
Thinking about it, 30s still seems quite high. 10s? |
// (Optional) cache size | ||
CacheLen int | ||
// (Optional) number of resolution workers for local queries | ||
NumLocalWorkers int |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
I don't see how there will ever be multiple RRs for a local (on the weave network) name: both the zone and the mdns client return just one RR, which the cache will take as a replacement for any existing answer. The only time multiple answers will come through is from a fallback query (arguably we ought not be permuting those). In fact, even if the zone or mDNS returned multiple RRs, they would get replaced in the cache, so it would always be the answers from one peer (us, or whoever answers mDNS first). |
I assume this comment is about the shuffle operation. I agree that we are not currently using this feature, but we could return multiple answers in the future (eg, #338). It should have no effect or performance cost when returning only one answer... |
In part; but see the second paragraph which I think is a more serious problem, unless I've misunderstood the code. |
Yes, I thought about that, but we could a) store in the cache the first response we receive (as you said) or b) apply some heuristics and merge all the responses, setting some reasonable values for things like TTLs, etc... |
Something like that would have to be done, yes, but also lookups would have to be tried in parallel (since in general you'd want to return all answers on the network). I think the interaction with the cache would be quite different, and possibly using mDNS wouldn't be workable. In any case, at the minute the behaviour will be:
whereas if we are sticking to single answers I think we want
|
Yes, there could be a periodic process that, for local queries, could try to get more answers with mDNS and merge answers and store them in the cache for future queries... |
3a00954
to
e2ac15c
Compare
The complexity will be in the gossiping, in the zone DB, in the cache, and in the interactions among them and with other code. Please can we solve one thing at a time, until it's demonstrated that e.g., caching local query responses -- as well as having the records in the zone DB -- is necessary. |
IMO that also applies to caching results of recursive queries. |
Do we know how well-known caching DNS servers, such as dnsmasq, perform caching? I am concerned that a cache keyed on the octet-sequence of a question, and storing entire answer sets, might be semantically suspect. |
@rade I think solutions applied by others do not need to be valid or applicable for us, as we do not have the resources others have (otherwise, we could reimplement BIND9 for Weave). Using the question as the key should be perfectly valid. A better granularity could lead to better cache usage, but that would add more complexity and I don't think we really need to optimize space here... Regarding recursive lookups, I do not understand why you are so reluctant to use the cache for them. I wouldn't underestimate these resolutions: they could have a big impact for users in some scenarios (e.g., a user setting |
The suggestion is to look for indications of what is the correct way to handle proxied responses -- whether it's OK to pass every record on. djbdns, for example, appears to do a lot of work to sanitise responses. If we aren't prepared to figure this out we have no business providing a caching name server.
Only if you think development and maintenance effort on our part, and troubleshooting and operation on our users' part, are free. |
@squaremo In conclusion, do you want to remove the cache for recursive queries? |
No, I just want us to be clear where we are providing benefit, and what the trade-off is. For example, many deployments will already have a caching nameserver, or be happily using 8.8.8.8, and in those deployments we are effectively adding needless machinery; some won't, but solutions exist already -- use dnsmasq or whatever -- and are we sure ours is really better? I know you've done some benchmarking, so perhaps you can make a quantitative argument in this direction. |
There are a bunch of RFCs pertaining to caching...
The upshot is that there is a lot to consider when caching answers from recursive queries. Most of these do not apply for local queries because, a) as Michael said, we really should consider the collection of all weaveDNS servers as a single server, and b) our servers only deal with a very limited number of query / record types. |
Ok, no problem, I'll remove caching for recursive resolutions. |
return func(w dns.ResponseWriter, r *dns.Msg) { | ||
q := r.Question[0] | ||
maxLen := getMaxReplyLen(r, proto) | ||
Debug.Printf("Query: %+v", q) | ||
if q.Qtype == dns.TypeA { |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
4204e45
to
90088c0
Compare
unit tests
@rade and @squaremo , I have updated this PR with the following changes:
Let me know what you think about this... |
What is the rationale behind keeping the heap of entries in order of expiry? I would have thought either of insertion time (nice and easy) or LRU (more trouble but more useful perhaps) would be preferable. |
@squaremo insertion time wouldn't give you the best order for getting rid of entries (could lead to useful entries being evicted before useless entries), and I'm not sure about the LRU (it would require more logic, and maybe it could make |
It depends what you think is useful or useless. An entry with a long TTL that is asked for very infrequently could be considered useless, while an fast-moving entry that gets asked for continually could be considered useful. Ordering the evictions by how soon they expire will tend to preserve the former while evicting the latter, sometimes ahead of schedule. Ordering by time of insertion means that you will tend to refresh (reinsert because of expiry) fast-moving entries well before they can get evicted, while slow-moving entries might make it to the top of the heap before being refreshed, but if so weren't being asked for very often anyway. |
#225 : this pull request implements a caching mechanism in the DNS server. The cache is used for saving positive and negative replies obtained by the local discovery system as well as by the recursive resolver.
Replies found in the cache are modified before being returned to clients by adjusting the remaining TTL and shuffling answers (implementing a basic load balancing mechanism as a side effect, a first step for #226).