如何使用Akka实现REST Web服务?

29

我打算采用纯Akka技术实现REST风格的Web API。我不确定是否使用spray框架,若好用我会考虑使用Scalatra。基本上,我想应用Scala Actor模型的并发优势,而不希望Servlet容器成为这一过程的障碍。

还有什么其他选项吗?

更新1:哪一个前端更适合在Akka后端实现REST?-Spray、Scalatra、Dropwizard还是其他什么?

6个回答

27
Akka的重要之处在于它不是一个全有或全无的环境。您可以在很大程度上混合和匹配不同的库,以组合适合您的系统。例如,我编写了使用Dropwizard作为前端,后端使用Akka的应用程序,没有问题。我也使用了Clothesline(用Clojure实现,但带有Scala包装器)做了同样的事情。本周晚些时候,我希望尝试使用Unfilteredwebsocket实现坐在Akka和RabbitMQ管道的前面,向客户端浏览器提供近乎实时的数据 - 我特别提到这个例子,因为Unfiltered websocket实现基于Netty而不是servlet容器。

更新:自从几年前写下这篇答案以来,我已经开始专门使用Spray进行与Akka相关的RESTful开发。虽然几乎任何JVM REST库都可以使用,但Spray非常自然地适合Akka的基于actor的模型,并且该库显然已经达到了易于成为默认选择的成熟水平。Spray即将集成到Akka中,成为新的akka-http模块,这是一个明确的指示。


我非常希望有人能够构建一个使用Jetty Continuations和/或Servlet 3.0 Async的Netty+Unfiltered版本,这样我就可以像那样将Akka集成进去了。如果方便的话,我非常好奇听听你作为一个整体的Akka经验。继续保持出色的工作,√ - Viktor Klang
1
如果时间允许的话,我很愿意帮忙添加这个功能。我知道已经有一些基础工作了,但很难感受到还有多少工作需要完成。而且这是我第一次尝试使用WebSockets(虽然我以前做过很多Comet),我对可能涉及的复杂性感到犹豫。 - Thomas Lockney
1
我在Unfiltered代码库方面的经验太少了,但我参与了Atmosphere项目并修复了Mist中的问题,因此我有相当多的Comet经验。不幸的是,Jonas现在正在度假,所以我非常忙碌,但我很想看到有人接手这个项目。Unfiltered具有出色的性能,因此将其与异步性结合使用将会非常棒。 - Viktor Klang
1
@Thomas,Dropwizard与Spray或Scalatra相比如何? - Kamesh Rao Yeduvakula
Unfiltered的WebSocket实现链接已经失效。 - seinecle
显示剩余3条评论

11

如果你需要相应的代码,那么这里是它。我花了一点时间来真正弄清楚到底发生了什么,因为有大量的示例,而且不清楚它们都在做什么或如何将它们组合起来。结果证明比我想象的要简单:

package com.nthalk.akkatest

import akka.actor.Actor.actorOf
import akka.actor.Actor
import akka.camel.Consumer
import akka.camel.Message
import akka.camel.CamelServiceManager

class MyActor extends Actor with Consumer {
  def endpointUri = "jetty:http://localhost:8877/"
  def receive = {
    case msg: Message => { self.reply("State Rest Service: Achieved") }
    case _ => { self.reply("Really, no message?") }
  }
}

object App extends scala.App {
  actorOf[MyActor].start
  CamelServiceManager.startCamelService
}

我的build.sbt文件如下:

organization := "com.nthalk"

name := "akkatest"

version := "0.1.0"

resolvers += 
  "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"

libraryDependencies ++= Seq(
  "org.apache.camel" % "camel-jetty" % "2.9.0",
  "se.scalablesolutions.akka" % "akka-camel" % "1.3.1"
  )

希望这可以帮助到你!


5

为了完整起见,似乎有一个Scalatra示例很有用(因为问题是关于Scalatra的)。这是来自Scalatra Akka Guide的一些示例代码:

package com.example.app

import akka.actor.{ActorRef, Actor, Props, ActorSystem}
import akka.dispatch.ExecutionContext
import akka.util.Timeout
import org.scalatra.FutureSupport
import org.scalatra.{Accepted, ScalatraServlet}

class MyActorApp(system:ActorSystem, myActor:ActorRef) extends ScalatraServlet with     FutureSupport {

  protected implicit def executor: ExecutionContext = system.dispatcher

  import _root_.akka.pattern.ask
  implicit val timeout = Timeout(10)

  get("/async") {
    new AsyncResult { def is = myActor ? "Do stuff and give me an answer" }
  }

  get("/fire-forget") {
    myActor ! "Hey, you know what?"
    Accepted()
  }
}

class MyActor extends Actor {
  def receive = {
    case "Do stuff and give me an answer" => sender ! "The answer is 42"
    case "Hey, you know what?" => println("Yeah I know... oh boy do I know")
  }

}

我在示例代码中遇到了以下错误:scala: 找不到隐式参数timeout的值:akka.util.Timeout new AsyncResult { val is = myActor ? "做一些事情并给我一个答案" } - Owen

3

3

使用基于akka-streams的akka-http(人们也称其为spray-2.0)。


0

我不知道你为什么怀疑使用Servlet容器作为基础——它实际上并不会限制你的选择,只是处理基本的HTTP服务器管道。

因此,大多数Java服务框架都使用Servlet API作为基础,即使它们不公开该级别。

我认为DropWizard是各种JVM REST服务的绝佳选择,包括那些使用Akka进行实际提升的服务。除了其优秀性(基于已被证明是“JVM最好”的库集合)之外,我喜欢它还因为它帮助解决了许多其他库/框架忽略的问题:生成度量数据、声明式验证;同时保持简单、明确和易于理解。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接