Document async and inetaddress DNS (#25414)

* Document async and inetaddress DNS

Closes #25307
This commit is contained in:
Christopher Batey 2018-09-17 08:11:34 +01:00 committed by GitHub
parent c132a81f0a
commit 8ba4de386f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 212 additions and 10 deletions

View file

@ -1,3 +1,5 @@
# #25435 - Adding maximum restart attempts to BackoffSupervisor
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.pattern.BackoffOptions.withMaxNrOfRetries")
# Change of a method name with ApiMayChange
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.io.dns.DnsProtocol#Resolve.create")

View file

@ -13,7 +13,17 @@ import com.typesafe.config.Config
import scala.collection.{ breakOut, immutable }
abstract class Dns {
/**
* Lookup if a DNS resolved is cached. The exact behavior of caching will depend on
* the akka.actor.io.dns.resolver that is configured.
*/
def cached(name: String): Option[Dns.Resolved] = None
/**
* If an entry is cached return it immediately. If it is not then
* trigger a resolve and return None.
*/
def resolve(name: String)(system: ActorSystem, sender: ActorRef): Option[Dns.Resolved] = {
val ret = cached(name)
if (ret.isEmpty)
@ -51,10 +61,18 @@ object Dns extends ExtensionId[DnsExt] with ExtensionIdProvider {
}
}
/**
* Lookup if a DNS resolved is cached. The exact behavior of caching will depend on
* the akka.actor.io.dns.resolver that is configured.
*/
def cached(name: String)(system: ActorSystem): Option[Resolved] = {
Dns(system).cache.cached(name)
}
/**
* If an entry is cached return it immediately. If it is not then
* trigger a resolve and return None.
*/
def resolve(name: String)(system: ActorSystem, sender: ActorRef): Option[Resolved] = {
Dns(system).cache.resolve(name)(system, sender)
}
@ -74,6 +92,7 @@ class DnsExt(val system: ExtendedActorSystem) extends IO.Extension {
val Settings = new Settings(system.settings.config.getConfig("akka.io.dns"))
class Settings private[DnsExt] (_config: Config) {
import _config._
val Dispatcher: String = getString("dispatcher")

View file

@ -48,18 +48,18 @@ object DnsProtocol {
object Resolve {
def apply(name: String): Resolve = Resolve(name, Ip())
/**
* Java API
*/
def create(name: String): Resolve = Resolve(name, Ip())
/**
* Java API
*/
def create(name: String, requestType: RequestType): Resolve = Resolve(name, requestType)
}
/**
* Java API
*/
def resolve(name: String): Resolve = Resolve(name, Ip())
/**
* Java API
*/
def resolve(name: String, requestType: RequestType): Resolve = Resolve(name, requestType)
/**
* @param name of the record
* @param records resource records for the query

View file

@ -10,6 +10,7 @@
* [io](io.md)
* [io-tcp](io-tcp.md)
* [io-udp](io-udp.md)
* [io-dns](io-dns.md)
* [camel](camel.md)
@@@

View file

@ -0,0 +1,74 @@
# DNS Extension
@@@ note
The `async-dns` API is marked as `ApiMayChange` as more information is expected to be added to the protocol.
@@@
Akka DNS is a pluggable way to interact with DNS. Implementations much implement `akka.io.DnsProvider` and provide a configuration
block that specifies the implementation via `provider-object`.
To select which `DnsProvider` to use set `akka.io.dns.resolver ` to the location of the configuration.
There are currently two implementations:
* `inet-address` - Based on the JDK's `InetAddress`. Using this will be subject to both the JVM's DNS cache and its built in one.
* `async-dns` - A native implemention of the DNS protocol that does not use any JDK classes or caches.
`inet-address` is the default implementation as it pre-dates `async-dns`, `async-dns` will likely become the default in the next major release.
DNS lookups can be done via the `DNS` extension:
Scala
: @@snip [DnsCompileOnlyDocSpec.scala](/akka-docs/src/test/scala/docs/actor/io/dns/DnsCompileOnlyDocSpec.scala) { #resolve }
Java
: @@snip [DnsCompileOnlyDocTest.java](/akka-docs/src/test/java/jdocs/actor/io/dns/DnsCompileOnlyDocTest.java) { #resolve }
Alternatively the `IO(Dns)` actor can be interacted with directly. However this exposes the different protocols of the DNS provider.
`inet-adddress` uses `Dns.Resolved` and `Dns.Resolved` where as the `async-dns` uses `DnsProtocol.Resolve` and `DnsProtocol.Resolved`.
The reason for the difference is `inet-address` predates `async-dns` and `async-dns` exposes additional information such as SRV records
and it wasn't possible to evolve the original API in a backward compatible way.
Inet-Address API:
Scala
: @@snip [IODocSpec.scala](/akka-docs/src/test/scala/docs/actor/io/dns/DnsCompileOnlyDocSpec.scala) { #actor-api-inet-address }
Java
: @@snip [DnsCompileOnlyDocTest.java](/akka-docs/src/test/java/jdocs/actor/io/dns/DnsCompileOnlyDocTest.java) { #actor-api-inet-address }
Async-DNS API:
Scala
: @@snip [IODocSpec.scala](/akka-docs/src/test/scala/docs/actor/io/dns/DnsCompileOnlyDocSpec.scala) { #actor-api-async }
Java
: @@snip [DnsCompileOnlyDocTest.java](/akka-docs/src/test/java/jdocs/actor/io/dns/DnsCompileOnlyDocTest.java) { #actor-api-async }
The Async DNS provider has the following advantages:
* No JVM DNS caching. It is expected that future versions will expose more caching related information.
* No blocking. `InetAddress` resolving is a blocking operation.
* Exposes `SRV`, `A` and `AAAA` records.
## SRV Records
To get DNS SRV records `akka.io.dns.resolver` must be set to `async-dns` and `DnsProtocol.Resolve`'s requestType
must be set to `DnsProtocol.Srv`
Scala
: @@snip [IODocSpec.scala](/akka-docs/src/test/scala/docs/actor/io/dns/DnsCompileOnlyDocSpec.scala) { #srv }
Java
: @@snip [DnsCompileOnlyDocTest.java](/akka-docs/src/test/java/jdocs/actor/io/dns/DnsCompileOnlyDocTest.java) { #srv }
The `DnsProtocol.Resolved` will contain `akka.io.dns.SRVRecord`s.

View file

@ -0,0 +1,57 @@
/*
* Copyright (C) 2018 Lightbend Inc. <https://www.lightbend.com>
*/
package jdocs.actor.io.dns;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.io.Dns;
import akka.io.IO;
import akka.io.dns.DnsProtocol;
import static akka.pattern.PatternsCS.ask;
import static akka.pattern.PatternsCS.pipe;
import scala.Option;
import java.util.concurrent.CompletionStage;
public class DnsCompileOnlyDocTest {
public static void example() {
ActorSystem system = ActorSystem.create();
ActorRef actorRef = null;
long timeout = 1000;
//#resolve
Option<Dns.Resolved> initial = Dns.get(system).cache().resolve("google.com", system, actorRef);
Option<Dns.Resolved> cached = Dns.get(system).cache().cached("google.com");
//#resolve
{
//#actor-api-inet-address
final ActorRef dnsManager = Dns.get(system).manager();
CompletionStage<Object> resolved = ask(dnsManager, new Dns.Resolve("google.com"), timeout);
//#actor-api-inet-address
}
{
//#actor-api-async
final ActorRef dnsManager = Dns.get(system).manager();
CompletionStage<Object> resolved = ask(dnsManager, DnsProtocol.resolve("google.com"), timeout);
//#actor-api-async
}
{
//#srv
final ActorRef dnsManager = Dns.get(system).manager();
CompletionStage<Object> resolved = ask(dnsManager, DnsProtocol.resolve("google.com", DnsProtocol.srvRequestType()), timeout);
//#srv
}
}
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (C) 2018 Lightbend Inc. <https://www.lightbend.com>
*/
package docs.actor.io.dns
import akka.actor.{ ActorRef, ActorSystem }
import akka.io.dns.DnsProtocol
import akka.io.dns.DnsProtocol.Srv
import akka.pattern.ask
import akka.io.{ Dns, IO }
import akka.util.Timeout
import scala.concurrent.Future
import scala.concurrent.duration._
object DnsCompileOnlyDocSpec {
implicit val system = ActorSystem()
implicit val timeout = Timeout(1.second)
val actorRef: ActorRef = ???
//#resolve
val initial: Option[Dns.Resolved] = Dns(system).cache.resolve("google.com")(system, actorRef)
val cached: Option[Dns.Resolved] = Dns(system).cache.cached("google.com")
//#resolve
{
//#actor-api-inet-address
val resolved: Future[Dns.Resolved] = (IO(Dns) ? Dns.Resolve("google.com")).mapTo[Dns.Resolved]
//#actor-api-inet-address
}
{
//#actor-api-async
val resolved: Future[DnsProtocol.Resolved] = (IO(Dns) ? DnsProtocol.Resolve("google.com")).mapTo[DnsProtocol.Resolved]
//#actor-api-async
}
{
//#srv
val resolved: Future[DnsProtocol.Resolved] = (IO(Dns) ? DnsProtocol.Resolve("your-service", Srv))
.mapTo[DnsProtocol.Resolved]
//#srv
}
}