5

TL;博士

我正在尝试遮蔽akka库的一个版本并将其与我的应用程序捆绑在一起(以便能够在 的版本上运行spray-can服务器)。着色过程弄乱了's 的默认配置,并且在手动为shaded提供了一个单独的's版本之后,看起来这两个版本仍然以某种方式混淆了。CDH 5.7Spark 1.6akkaakkareference.confakka

是否已知着色akka版本会导致问题?我究竟做错了什么?

背景

我有一个Scala/Spark应用程序当前Spark 1.6.1独立运行。该应用程序使用 运行spray-canhttp 服务器spray 1.3.3,这需要akka 2.3.9Spark 1.6.1独立包括兼容的akka 2.3.11)。

我正在尝试将应用程序Cloudera迁移到Spark运行. 问题是与in捆绑在一起不足以正常运行。CDH 5.7Spark 1.6Spark 1.6CDH 5.7akka 2.2.3spray 1.3.3

尝试的解决方案

按照这篇文章中的建议,我决定将akka 2.3.9它与我的应用程序一起遮蔽并捆绑在一起。虽然这次我偶然发现了一个新问题——akka它的默认配置是否定义在一个reference.conf文件中,该文件应该位于应用程序的类路径中。由于的着色功能中的一个已知问题sbt-assembly,着色akka库似乎需要单独的配置。

因此,我最终akka使用以下阴影规则进行着色:

ShadeRule.rename("akka.**" -> "akka_2_3_9_shade.@1")
    .inLibrary("com.typesafe.akka" % "akka-actor_2.10" % "2.3.9")
    .inAll

reference.conf并在我的项目中包含一个附加文件,该文件与akka's original相同reference.conf,但所有出现的“akka”都替换为“akka_2_3_9_shade”。

但是,现在似乎Spark-providedakka以某种方式与 shaded 混淆了akka,因为我收到以下错误:

Exception in thread "main" java.lang.IllegalArgumentException: Cannot instantiate MailboxType [akka.dispatch.UnboundedMailbox], defined in [akka.actor.default-mailbox], make sure it has a public constructor with [akka.actor.ActorSystem.Settings, com.typesafe.config.Config] parameters
    at akka_2_3_9_shade.dispatch.Mailboxes$$anonfun$1.applyOrElse(Mailboxes.scala:197)
    at akka_2_3_9_shade.dispatch.Mailboxes$$anonfun$1.applyOrElse(Mailboxes.scala:195)
    at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:33)
    at scala.util.Failure$$anonfun$recover$1.apply(Try.scala:185)
    at scala.util.Try$.apply(Try.scala:161)
    at scala.util.Failure.recover(Try.scala:185)
    at akka_2_3_9_shade.dispatch.Mailboxes.lookupConfiguration(Mailboxes.scala:195)
    at akka_2_3_9_shade.dispatch.Mailboxes.lookup(Mailboxes.scala:78)
    at akka_2_3_9_shade.actor.LocalActorRefProvider.akka$actor$LocalActorRefProvider$$defaultMailbox$lzycompute(ActorRefProvider.scala:561)
    at akka_2_3_9_shade.actor.LocalActorRefProvider.akka$actor$LocalActorRefProvider$$defaultMailbox(ActorRefProvider.scala:561)
    at akka_2_3_9_shade.actor.LocalActorRefProvider$$anon$1.<init>(ActorRefProvider.scala:568)
    at akka_2_3_9_shade.actor.LocalActorRefProvider.rootGuardian$lzycompute(ActorRefProvider.scala:564)
    at akka_2_3_9_shade.actor.LocalActorRefProvider.rootGuardian(ActorRefProvider.scala:563)
    at akka_2_3_9_shade.actor.LocalActorRefProvider.init(ActorRefProvider.scala:618)
    at akka_2_3_9_shade.actor.ActorSystemImpl.liftedTree2$1(ActorSystem.scala:619)
    at akka_2_3_9_shade.actor.ActorSystemImpl._start$lzycompute(ActorSystem.scala:616)
    at akka_2_3_9_shade.actor.ActorSystemImpl._start(ActorSystem.scala:616)
    at akka_2_3_9_shade.actor.ActorSystemImpl.start(ActorSystem.scala:633)
    at akka_2_3_9_shade.actor.ActorSystem$.apply(ActorSystem.scala:142)
    at akka_2_3_9_shade.actor.ActorSystem$.apply(ActorSystem.scala:109)
    at akka_2_3_9_shade.actor.ActorSystem$.apply(ActorSystem.scala:100)
    at MyApp.api.Boot$delayedInit$body.apply(Boot.scala:45)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:71)
    at scala.App$$anonfun$main$1.apply(App.scala:71)
    at scala.collection.immutable.List.foreach(List.scala:318)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
    at scala.App$class.main(App.scala:71)
    at MyApp.api.Boot$.main(Boot.scala:28)
    at MyApp.api.Boot.main(Boot.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:731)
    at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:181)
    at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:206)
    at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:121)
    at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.lang.ClassCastException: interface akka_2_3_9_shade.dispatch.MailboxType is not assignable from class akka.dispatch.UnboundedMailbox
    at akka_2_3_9_shade.actor.ReflectiveDynamicAccess$$anonfun$getClassFor$1.apply(DynamicAccess.scala:69)
    at akka_2_3_9_shade.actor.ReflectiveDynamicAccess$$anonfun$getClassFor$1.apply(DynamicAccess.scala:66)
    at scala.util.Try$.apply(Try.scala:161)
    at akka_2_3_9_shade.actor.ReflectiveDynamicAccess.getClassFor(DynamicAccess.scala:66)
    at akka_2_3_9_shade.actor.ReflectiveDynamicAccess.CreateInstanceFor(DynamicAccess.scala:84)
    ... 34 more

我的应用程序文件中的相关代码Boot.scala如下:

[45]    implicit val system = ActorSystem()
...
[48]    val service = system.actorOf(Props[MyAppApiActor], "MyApp.Api")
...
[52]    val port = config.getInt("MyApp.server.port")
[53]    IO(Http) ? Http.Bind(service, interface = "0.0.0.0", port = port)
4

3 回答 3

6

好的,所以最终我设法解决了这个问题。

结果akka使用定义为字符串文字的键从配置文件中加载(某些)配置设置。例如,您可以在 中找到很多这样的内容akka/actor/ActorSystem.scala

而且似乎sbt-assembly 不会更改对字符串文字中阴影库/包名称的引用。

此外,一些配置键正在sbt-assembly's 的阴影所改变。我并没有真正花时间找到它们在akka源代码中的定义位置和方式,但是在初始化代码期间抛出的以下异常ActorSystem证明确实如此:

ConfigException$Missing: No configuration setting found for key 'akka_2_3_9_shade'

因此,解决方案是包含一个自定义配置文件(例如调用它akka_spray_shade.conf),并在其中复制以下配置部分:

  • akka的原始内容reference.conf,但akka配置值中的前缀更改为akka_2_3_9_shade. (这是硬编码字符串文字配置键所必需的)
  • akka的原始内容reference.conf,但akka配置值中的前缀更改为akka_2_3_9_shade ,根配置键从更改akkaakka_2_3_9_shade。(这是由 修改的配置键所必需的sbt-assembly
  • spray的原始内容reference.conf,但akka配置值中的前缀更改为akka_2_3_9_shade. (这是确保spray始终指代阴影所必需的akka

现在,必须在初始化应用程序代码期间显式提供此自定义配置文件:ActorSystemBoot.scala

val akkaShadeConfig = ConfigFactory.load("akka_spray_shade")
implicit val system = ActorSystem("custom-actor-system-name", akkaShadeConfig)
于 2016-11-28T12:11:37.733 回答
1

对已接受的答案的一个小补充。

不必将此配置放在自定义命名的文件中,例如akka_spray_shade.conf. 当没有明确指定自定义配置时,可以放置application.conf在创建期间默认加载的配置:有效地意味着.ActorSystemActorSystem("custom-actor-system-name")ActorSystem("custom-actor-system-name", ConfigFactory.load("application"))

于 2017-10-24T12:03:50.617 回答
1

我也为此苦苦挣扎了很长时间。事实证明,默认的合并策略sbt-assembly排除了所有reference.conf文件。添加这个来build.sbt为我解决它:

assemblyMergeStrategy in assembly := {
  case PathList("reference.conf") => MergeStrategy.concat
}
于 2021-07-13T06:33:35.693 回答