-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Async DNS over TCP #25690
Async DNS over TCP #25690
Conversation
} | ||
|
||
"resolve queries that are too big for UDP" in { | ||
val name = "many.bzzt.net" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this still up? Not working for me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should! (serving AAAA records)
Test FAILed. |
47e7e4a
to
42ed417
Compare
Test PASSed. |
Test FAILed. |
Test FAILed. |
(cancelled 2 builds to make some room on Jenkins, we're mostly interested in the newest commit after all) |
Test PASSed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a partial review...
minBackoff = 10.millis, | ||
maxBackoff = 20.seconds, | ||
randomFactor = 0.1 | ||
), "tcpDnsClientSupervisor") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm guessing this only happens for the SRV use case, not normal DNS, so should we perhaps start it lazily instead of always?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In theory it can also happen for large normal DNS responses, but I agree that is a corner case and it'd make sense to start this lazily
} | ||
} else { | ||
val (recs, additionalRecs) = if (msg.flags.responseCode == ResponseCode.SUCCESS) (msg.answerRecs, msg.additionalRecs) else (Nil, Nil) | ||
self ! Answer(msg.id, recs, additionalRecs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to reschedule it a message, couldn't we just deal with the result right away?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in the truncated case, it's the TcpDnsClient
that sends the Answer
to the DnsClient
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could it not get the replyTo out of the inflightRequests then send it back right away?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chbatey I'm not sure I follow. The reason we're sending Answer
to self
here because that makes it possible to share that logic with the code path where TcpDnsClient
sends the Answer
to us. We could also put that logic in a helper function and call that helper function here and when we receive an Answer
from TcpDnsClient
, do you think that would be clearer?
val connecting: Receive = { | ||
case CommandFailed(_: Connect) ⇒ | ||
log.warning("Failed to connect to [{}]", ns) | ||
throw new AkkaException("Connecting failed") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't just throwing going to lead to it getting logged? Put the ns
in the exception instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably, but that might not be bad? Weird if connecting to the DNS server fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly thinking that if we get two errors in the log that is confusing but maybe it doesn't matter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, good one, will remove the warning
👍
|
||
private def parseResponse(data: ByteString) = { | ||
val msg = Message.parse(data) | ||
log.debug(s"Decoded: $msg") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
debug("Decoded: {}", msg)
case msg: Message ⇒ | ||
val bytes = msg.write() | ||
connection ! Tcp.Write(encodeLength(bytes.length)) | ||
connection ! Tcp.Write(bytes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do them with one write message?
if (data.drop(prefixSize).length < expectedPayloadLength) | ||
context.become(ready(connection, data)) | ||
else { | ||
val payload = data.drop(prefixSize).take(expectedPayloadLength) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't there something with drop and take on ByteStrings being overly expensive?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're doing I/O anyway and we need to seek in the message while parsing references to domain names, I think the drop
is worth it. The take
we can skip, though.
Test PASSed. |
Test PASSed. |
Test FAILed. |
Test FAILed. |
PLS BUILD |
Test PASSed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, looks good
} | ||
} else { | ||
val (recs, additionalRecs) = if (msg.flags.responseCode == ResponseCode.SUCCESS) (msg.answerRecs, msg.additionalRecs) else (Nil, Nil) | ||
self ! Answer(msg.id, recs, additionalRecs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could it not get the replyTo out of the inflightRequests then send it back right away?
|
||
val idle: Receive = { | ||
case _: Message ⇒ | ||
stash() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the stash will never get too big if the dns server doesn't support TCP as we'll restart back a backoff
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
val bytes = msg.write() | ||
connection ! Tcp.Write(encodeLength(bytes.length) ++ bytes) | ||
case CommandFailed(_: Write) ⇒ | ||
throw new AkkaException("Write failed") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it include any reason for the failure that we want to have logged?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha - I expected not, but CommandFailed
actually has a cause: Option[Throwable]
. I'll see if I can add a 'log' here.
Test PASSed. |
Refs #25460
The current implementation includes an integration test that relies on being online and receiving a truncated response when resolving the
AAAA
records formany.bzzt.net
. We're considering creating a Docker image that acts as a DNS server that shows the behavior we want to test against.