Make netty and aeron dependencies optional (#27017)

* Make netty and aeron dependencies optional
* Include agrona as a mandatory dependency (used in compression tables)
Refs #25169
This commit is contained in:
Christopher Batey 2019-05-29 09:50:28 +01:00 committed by GitHub
parent cd6d90097e
commit 96eed177dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 92 additions and 9 deletions

View file

@ -123,7 +123,9 @@ blocking and protect a bit against starving the internal actors. Since the inter
the default dispatcher has been adjusted down to `1.0` which means the number of threads will be one per core, but at least the default dispatcher has been adjusted down to `1.0` which means the number of threads will be one per core, but at least
`8` and at most `64`. This can be tuned using the individual settings in `akka.actor.default-dispatcher.fork-join-executor`. `8` and at most `64`. This can be tuned using the individual settings in `akka.actor.default-dispatcher.fork-join-executor`.
## Default remoting is now Artery TCP @@ Remoting
### Default remoting is now Artery TCP
@ref[Artery TCP](../remoting-artery.md) is now the default remoting implementation. @ref[Artery TCP](../remoting-artery.md) is now the default remoting implementation.
Classic remoting has been deprecated and will be removed in `2.7.0`. Classic remoting has been deprecated and will be removed in `2.7.0`.
@ -134,7 +136,7 @@ Previously, Akka contained a shaded copy of the ForkJoinPool. In benchmarks, we
keeping our own copy, so from Akka 2.6 on, the default FJP from the JDK will be used. The Akka FJP copy was removed. keeping our own copy, so from Akka 2.6 on, the default FJP from the JDK will be used. The Akka FJP copy was removed.
<a id="classic-to-artery"></a> <a id="classic-to-artery"></a>
### Migrating from classic remoting to Artery #### Migrating from classic remoting to Artery
Artery has the same functionality as classic remoting and you should normally only have to change the Artery has the same functionality as classic remoting and you should normally only have to change the
configuration to switch. configuration to switch.
@ -164,7 +166,7 @@ If using SSL then `tcp-tls` needs to be enabled and setup. See @ref[Artery docs
for how to do this. for how to do this.
### Migration from 2.5.x Artery to 2.6.x Artery #### Migration from 2.5.x Artery to 2.6.x Artery
The following defaults have changed: The following defaults have changed:
@ -189,18 +191,23 @@ For TCP:
* `akka.remote.artery.advanced.connection-timeout` to `akka.remote.artery.advanced.tcp.connection-timeout` * `akka.remote.artery.advanced.connection-timeout` to `akka.remote.artery.advanced.tcp.connection-timeout`
### Remaining with Classic remoting (not recommended) #### Remaining with Classic remoting (not recommended)
Classic remoting is deprecated but can be used in `2.6.` Any configuration under `akka.remote` that is Classic remoting is deprecated but can be used in `2.6.` Any configuration under `akka.remote` that is
specific to classic remoting needs to be moved to `akka.remote.classic`. To see which configuration options specific to classic remoting needs to be moved to `akka.remote.classic`. To see which configuration options
are specific to classic search for them in: [`akka-remote/reference.conf`](/akka-remote/src/main/resources/reference.conf) are specific to classic search for them in: [`akka-remote/reference.conf`](/akka-remote/src/main/resources/reference.conf)
## Netty UDP has been removed ### Netty UDP has been removed
Classic remoting over UDP has been deprecated since `2.5.0` and now has been removed. Classic remoting over UDP has been deprecated since `2.5.0` and now has been removed.
To continue to use UDP configure @ref[Artery UDP](../remoting-artery.md#configuring-ssl-tls-for-akka-remoting) or migrate to Artery TCP. To continue to use UDP configure @ref[Artery UDP](../remoting-artery.md#configuring-ssl-tls-for-akka-remoting) or migrate to Artery TCP.
A full cluster restart is required to change to Artery. A full cluster restart is required to change to Artery.
### Remoting dependencies have been made optional
Classic remoting depends on Netty and Artery UDP depends on Aeron. These are now both optional dependencies that need
to be explicitly added. See @ref[classic remoting](../remoting.md) or [artery remoting](../remoting-artery.md) for instructions.
## Streams ## Streams
### StreamRefs ### StreamRefs

View file

@ -23,6 +23,18 @@ To use Artery Remoting, you must add the following dependency in your project:
version=$akka.version$ version=$akka.version$
} }
Artery UDP depends on Aeron. This needs to be explicitly added as a dependency if using `aeron-udp` so that users
not using Artery remoting do not have Aeron on the classpath:
@@dependency[sbt,Maven,Gradle] {
group=io.aeron
artifact=aeron-driver
version="$aeron_version$"
group2=io.aeron
artifact2=aeron-client
version2="$aeron_version$"
}
If migrating from classic remoting see @ref:[what's new in Artery](#what-is-new-in-artery) If migrating from classic remoting see @ref:[what's new in Artery](#what-is-new-in-artery)
## Configuration ## Configuration

View file

@ -30,6 +30,15 @@ To use Akka Remoting, you must add the following dependency in your project:
version=$akka.version$ version=$akka.version$
} }
Classic remoting depends on Netty. This needs to be explicitly added as a dependency so that users
not using classic remoting do not have to have Netty on the classpath:
@@dependency[sbt,Maven,Gradle] {
group=io.netty
artifact=netty
version=$netty_version$
}
## Configuration ## Configuration
To enable classic remoting in your Akka project you should, at a minimum, add the following changes To enable classic remoting in your Akka project you should, at a minimum, add the following changes

View file

@ -12,6 +12,7 @@ import akka.event.Logging.Error
import akka.pattern.pipe import akka.pattern.pipe
import scala.util.control.NonFatal import scala.util.control.NonFatal
import scala.util.Failure
import akka.actor.SystemGuardian.{ RegisterTerminationHook, TerminationHook, TerminationHookDone } import akka.actor.SystemGuardian.{ RegisterTerminationHook, TerminationHook, TerminationHookDone }
import scala.util.control.Exception.Catcher import scala.util.control.Exception.Catcher
@ -22,6 +23,7 @@ import akka.dispatch.{ RequiresMessageQueue, UnboundedMessageQueueSemantics }
import akka.remote.artery.ArteryTransport import akka.remote.artery.ArteryTransport
import akka.remote.artery.aeron.ArteryAeronUdpTransport import akka.remote.artery.aeron.ArteryAeronUdpTransport
import akka.remote.artery.ArterySettings import akka.remote.artery.ArterySettings
import akka.remote.artery.ArterySettings.AeronUpd
import akka.util.{ ErrorMessages, OptionVal } import akka.util.{ ErrorMessages, OptionVal }
import akka.remote.artery.OutboundEnvelope import akka.remote.artery.OutboundEnvelope
import akka.remote.artery.SystemMessageDelivery.SystemMessageEnvelope import akka.remote.artery.SystemMessageDelivery.SystemMessageEnvelope
@ -35,6 +37,7 @@ import com.github.ghik.silencer.silent
*/ */
@InternalApi @InternalApi
private[akka] object RemoteActorRefProvider { private[akka] object RemoteActorRefProvider {
private final case class Internals(transport: RemoteTransport, remoteDaemon: InternalActorRef) private final case class Internals(transport: RemoteTransport, remoteDaemon: InternalActorRef)
extends NoSerializationVerificationNeeded extends NoSerializationVerificationNeeded
@ -207,6 +210,12 @@ private[akka] class RemoteActorRefProvider(
remoteSettings.configureDispatcher(Props(classOf[RemotingTerminator], local.systemGuardian)), remoteSettings.configureDispatcher(Props(classOf[RemotingTerminator], local.systemGuardian)),
"remoting-terminator") "remoting-terminator")
if (remoteSettings.Artery.Enabled && remoteSettings.Artery.Transport == AeronUpd) {
checkAeronOnClassPath(system)
} else if (!remoteSettings.Artery.Enabled) {
checkNettyOnClassPath(system)
} // artery tcp has no dependencies
val internals = Internals( val internals = Internals(
remoteDaemon = { remoteDaemon = {
val d = new RemoteSystemDaemon( val d = new RemoteSystemDaemon(
@ -239,6 +248,38 @@ private[akka] class RemoteActorRefProvider(
remoteDeploymentWatcher = createRemoteDeploymentWatcher(system) remoteDeploymentWatcher = createRemoteDeploymentWatcher(system)
} }
private def checkNettyOnClassPath(system: ActorSystemImpl): Unit = {
// TODO change link to current once 2.6 is out
checkClassOrThrow(
system,
"org.jboss.netty.channel.Channel",
"Classic",
"Netty",
"https://doc.akka.io/docs/akka/2.6/remoting.html")
}
private def checkAeronOnClassPath(system: ActorSystemImpl): Unit = {
// TODO change link to current once 2.6 is out
val arteryLink = "https://doc.akka.io/docs/akka/2.6/remoting-artery.html"
// using classes that are used so will fail to compile if they get removed from Aeron
checkClassOrThrow(system, "io.aeron.driver.MediaDriver", "Artery", "Aeron driver", arteryLink)
checkClassOrThrow(system, "io.aeron.Aeron", "Artery", "Aeron client", arteryLink)
}
private def checkClassOrThrow(
system: ActorSystemImpl,
className: String,
remoting: String,
libraryMissing: String,
link: String): Unit = {
system.dynamicAccess.getClassFor(className) match {
case Failure(_: ClassNotFoundException | _: NoClassDefFoundError) =>
throw new IllegalStateException(
s"$remoting remoting is enabled but $libraryMissing is not on the classpath, it must be added explicitly. See $link")
case _ =>
}
}
protected def createRemoteWatcher(system: ActorSystemImpl): ActorRef = { protected def createRemoteWatcher(system: ActorSystemImpl): ActorRef = {
import remoteSettings._ import remoteSettings._
val failureDetector = createRemoteWatcherFailureDetector(system) val failureDetector = createRemoteWatcherFailureDetector(system)

View file

@ -222,7 +222,9 @@ lazy val docs = akkaModule("akka-docs")
"google.analytics.domain.name" -> "akka.io", "google.analytics.domain.name" -> "akka.io",
"signature.akka.base_dir" -> (baseDirectory in ThisBuild).value.getAbsolutePath, "signature.akka.base_dir" -> (baseDirectory in ThisBuild).value.getAbsolutePath,
"fiddle.code.base_dir" -> (sourceDirectory in Test).value.getAbsolutePath, "fiddle.code.base_dir" -> (sourceDirectory in Test).value.getAbsolutePath,
"fiddle.akka.base_dir" -> (baseDirectory in ThisBuild).value.getAbsolutePath), "fiddle.akka.base_dir" -> (baseDirectory in ThisBuild).value.getAbsolutePath,
"aeron_version" -> Dependencies.aeronVersion,
"netty_version" -> Dependencies.nettyVersion),
Compile / paradoxGroups := Map("Language" -> Seq("Scala", "Java")), Compile / paradoxGroups := Map("Language" -> Seq("Scala", "Java")),
resolvers += Resolver.jcenterRepo, resolvers += Resolver.jcenterRepo,
apidocRootPackage := "akka", apidocRootPackage := "akka",
@ -251,6 +253,7 @@ lazy val jackson = akkaModule("akka-serialization-jackson")
lazy val multiNodeTestkit = akkaModule("akka-multi-node-testkit") lazy val multiNodeTestkit = akkaModule("akka-multi-node-testkit")
.dependsOn(remote, testkit) .dependsOn(remote, testkit)
.settings(Dependencies.multiNodeTestkit)
.settings(Protobuf.settings) .settings(Protobuf.settings)
.settings(AutomaticModuleName.settings("akka.remote.testkit")) .settings(AutomaticModuleName.settings("akka.remote.testkit"))
.settings(AkkaBuild.mayChangeSettings) .settings(AkkaBuild.mayChangeSettings)

View file

@ -17,7 +17,11 @@ object Dependencies {
val junitVersion = "4.12" val junitVersion = "4.12"
val slf4jVersion = "1.7.25" val slf4jVersion = "1.7.25"
val scalaXmlVersion = "1.0.6" val scalaXmlVersion = "1.0.6"
// check agrona version when updating this
val aeronVersion = "1.15.1" val aeronVersion = "1.15.1"
// needs to be inline with the aeron version
val agronaVersion = "0.9.31"
val nettyVersion = "3.10.6.Final"
val jacksonVersion = "2.9.9" val jacksonVersion = "2.9.9"
val scala212Version = "2.12.8" val scala212Version = "2.12.8"
@ -52,7 +56,7 @@ object Dependencies {
// Compile // Compile
val config = "com.typesafe" % "config" % "1.3.4" // ApacheV2 val config = "com.typesafe" % "config" % "1.3.4" // ApacheV2
val netty = "io.netty" % "netty" % "3.10.6.Final" // ApacheV2 val netty = "io.netty" % "netty" % nettyVersion // ApacheV2
val scalaXml = "org.scala-lang.modules" %% "scala-xml" % scalaXmlVersion // Scala License val scalaXml = "org.scala-lang.modules" %% "scala-xml" % scalaXmlVersion // Scala License
val scalaReflect = ScalaVersionDependentModuleID.versioned("org.scala-lang" % "scala-reflect" % _) // Scala License val scalaReflect = ScalaVersionDependentModuleID.versioned("org.scala-lang" % "scala-reflect" % _) // Scala License
@ -82,6 +86,8 @@ object Dependencies {
val aeronDriver = "io.aeron" % "aeron-driver" % aeronVersion // ApacheV2 val aeronDriver = "io.aeron" % "aeron-driver" % aeronVersion // ApacheV2
val aeronClient = "io.aeron" % "aeron-client" % aeronVersion // ApacheV2 val aeronClient = "io.aeron" % "aeron-client" % aeronVersion // ApacheV2
// Added explicitly for when artery tcp is used
val agrona = "org.agrona" % "agrona" % agronaVersion // ApacheV2
val jacksonCore = "com.fasterxml.jackson.core" % "jackson-core" % jacksonVersion // ApacheV2 val jacksonCore = "com.fasterxml.jackson.core" % "jackson-core" % jacksonVersion // ApacheV2
val jacksonAnnotations = "com.fasterxml.jackson.core" % "jackson-annotations" % jacksonVersion // ApacheV2 val jacksonAnnotations = "com.fasterxml.jackson.core" % "jackson-annotations" % jacksonVersion // ApacheV2
@ -180,9 +186,14 @@ object Dependencies {
val actorTestkitTyped = l ++= Seq(Provided.junit, Provided.scalatest.value) val actorTestkitTyped = l ++= Seq(Provided.junit, Provided.scalatest.value)
val remote = l ++= Seq(netty, aeronDriver, aeronClient, Test.junit, Test.scalatest.value, Test.jimfs) val remoteDependencies = Seq(netty, aeronDriver, aeronClient)
val remoteOptionalDependencies = remoteDependencies.map(_ % "optional")
val remoteTests = l ++= Seq(Test.junit, Test.scalatest.value, Test.scalaXml) val remote = l ++= Seq(agrona, Test.junit, Test.scalatest.value, Test.jimfs) ++ remoteOptionalDependencies
val remoteTests = l ++= Seq(Test.junit, Test.scalatest.value, Test.scalaXml) ++ remoteDependencies
val multiNodeTestkit = l ++= remoteOptionalDependencies
val cluster = l ++= Seq(Test.junit, Test.scalatest.value) val cluster = l ++= Seq(Test.junit, Test.scalatest.value)