【问题标题】:Error while doing a very basic test of http server using scala akka spray can使用 scala akka spray 对 http 服务器进行非常基本的测试时出错
【发布时间】:2014-07-12 15:52:21
【问题描述】:

我做了一个非常基本的喷雾罐测试:

  • Akka 2.10 2.24
  • Scala 2.10.3
  • 喷雾罐 1.3.1
  • sbt 0.13
  • IntelliJ 13

这是我的代码:

val myListener: ActorRef = system.actorOf(Props[TestHttpListener], "httpListener")
IO(Http) ! Http.Bind(myListener, interface = "localhost", port = 8080)

httpListenerHttp.Register(self) 响应 Http.Connected

我使用 sbt 来运行我的代码。它以AbstractMethodError 失败:

[ERROR] [07/12/2014 18:46:48.364] [default-akka.actor.default-dispatcher-5] [ActorSystem(default)] Uncaught error from thread [default-akka.actor.default-dispatcher-5] shutting down JVM since 'akka.jvm-exit-on-fatal-error' is enabled
java.lang.AbstractMethodError: spray.can.HttpManager.akka$actor$ActorLogging$_setter_$log_$eq(Lakka/event/LoggingAdapter;)V
        at akka.actor.ActorLogging$class.$init$(Actor.scala:335)
        at spray.can.HttpManager.<init>(HttpManager.scala:29)
        at spray.can.HttpExt$$anonfun$1.apply(Http.scala:153)
        at spray.can.HttpExt$$anonfun$1.apply(Http.scala:153)
        at akka.actor.TypedCreatorFunctionConsumer.produce(Props.scala:422)
        at akka.actor.Props.newActor(Props.scala:331)
        at akka.actor.ActorCell.newActor(ActorCell.scala:534)
        at akka.actor.ActorCell.create(ActorCell.scala:560)
        at akka.actor.dungeon.FaultHandling$class.finishCreate(FaultHandling.scala:135)
        at akka.actor.dungeon.FaultHandling$class.faultCreate(FaultHandling.scala:129)
        at akka.actor.ActorCell.faultCreate(ActorCell.scala:338)
        at akka.actor.dungeon.FaultHandling$class.faultRecreate(FaultHandling.scala:58)
        at akka.actor.ActorCell.faultRecreate(ActorCell.scala:338)
        at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:428)
        at akka.actor.ActorCell.systemInvoke(ActorCell.scala:447)
        at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:262)
        at akka.dispatch.Mailbox.run(Mailbox.scala:218)
        at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:385)
        at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
        at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
        at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
        at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

【问题讨论】:

  • 似乎actor日志记录的版本与喷雾所期望的不同。您可以尝试使用inspect test 或类似的东西检查sbt 中的依赖关系吗?
  • 您好,谢谢,这就是问题所在:我没有为我正在使用的 spray 版本使用合适的 akka-core 依赖版本。谢谢!
  • 酷。添加了答案,以便其他人可以轻松查看正确的解决方案。

标签: scala akka httpserver spray


【解决方案1】:

在 Scala 世界中,谨慎对待版本非常重要,因为一切都在快速发展,并且无法保证主要版本之间的向后兼容性。

Spray 取决于 Akkathis page 包含有关支持组合的信息。

spray 1.3.1 是针对 Scala 2.10.3 和 Akka 2.3.0 以及 Scala 2.11.1 和 Akka 2.3.2 构建的。

因此,如果您使用 Scala 2.10.3,则 Akka 的正确版本至少应为 2.3.0。

此外,我认为您从this 页面关注的示例不是很好。

首先,它忽略了这样一个事实,即使用IO(Http) ! Http.Bind(...) 初始化事物的代码必须在演员内部。收到Http.Bind 的演员尝试回复Http.Bound,由于来电者不是演员,您会收到死信。

所以,我建议这样做:

class MyApp extends Actor {

  implicit val system = context.system

  override def receive: Receive = {
    case "start" =>
      val myListener: ActorRef = system.actorOf(Props[TestHttpListener], "httpListener")
      IO(Http) ! Http.Bind(myListener, interface = "localhost", port = 8080)
  }
}

然后从你的应用程序的main() 方法中你需要做:

val myApp: ActorRef = system.actorOf(Props[MyApp], "myApp")
myApp ! "start"

从示例中不太容易理解的另一件事是,在您的侦听器 Actor 中,您不仅需要处理消息,还需要在每个连接上注册自己:

class TestHttpListener extends Actor {
  def receive = {
    case HttpRequest(HttpMethods.GET, Uri.Path("/ping"), _, _, _) =>
      sender() ! HttpResponse(entity = "PONG")

    case c : Tcp.Connected =>
      sender() ! Http.Register(self)
  }
}

【讨论】:

  • 谢谢。但是,我现在有另一个问题:( http.Bind 失败了,我也不知道为什么:一个底层的演员被设置为死信,并且没有收到一些消息。但我想这是另一个问题和问题......
  • @Joel 我在答案中添加了一些可能有帮助的信息。
  • 谢谢。我不知道我怎么会猜到,我很沮丧官方文档是错误的!这种技术很有趣,但它是一场噩梦。不幸的是,绑定仍然失败。当我写val myListener: ActorRef = system.actorOf(Props[TestHttpListener], "httpListener") 时,我在绑定时收到警告,然后是与死信箱相关的消息。当我写val myListener: ActorRef = context.actorOf(Props[TestHttpListener], "httpListener") 时,我只是收到警告,没有任何死信箱问题。我将花 2 天时间来启动一个 http 服务器 :(
  • 今天有效。我不知道我做了什么,因为我根本没有更改代码。但是昨天晚上我升级了 IntelliJ 和 SBT 插件。似乎 IntelliJ 在 scala 项目方面存在一些问题。非常感谢。
  • 实际上我遇到了一个寄存器超时错误。在这里我不熟悉 scala 差异:如果我输入case m @ Http.Connected =&gt; sender ! Http.Register(self),它就不起作用。如果我输入case _ : Http.Connected =&gt; sender ! Http.Register(self),它可以工作。我不知道语义上的差异,这对我来说很奇怪。
猜你喜欢
  • 1970-01-01
  • 2016-06-19
  • 2016-04-24
  • 1970-01-01
  • 2016-05-10
  • 1970-01-01
  • 1970-01-01
  • 2013-05-23
  • 2015-10-25
相关资源
最近更新 更多