如何扩展使用Akka的Scala REST应用程序?

如何扩展使用Akka的Scala REST应用程序?,scala,rest,jersey,akka,scalability,Scala,Rest,Jersey,Akka,Scalability,我有一个使用Akka的Scala应用程序,它接收REST请求,对数据库进行一些操作,并向客户机发送一些信息。事实上,我的db操作需要很长时间,并且我的支持REST的actor无法同时响应新请求,即使我可以对db同时运行许多操作。我正在使用javax.ws.rs注释在我的actor中启用REST方法 问题,;使我的应用程序能够处理大量并发请求的最佳方法是什么 编辑:我将添加一些示例代码 import se.scalablesolutions.akka.actor._ import java

我有一个使用Akka的Scala应用程序,它接收REST请求,对数据库进行一些操作,并向客户机发送一些信息。事实上,我的db操作需要很长时间,并且我的支持REST的actor无法同时响应新请求,即使我可以对db同时运行许多操作。我正在使用javax.ws.rs注释在我的actor中启用REST方法

问题,;使我的应用程序能够处理大量并发请求的最佳方法是什么

编辑:我将添加一些示例代码

  import se.scalablesolutions.akka.actor._
  import javax.ws.rs._

  @Path("/test")
  class TestService {

    @GET
    def status() = 
      actorPool !! Status(session).
        getOrElse(<error>Unable to connect to service</error>)
  }

  class TestActor {

    def receive = {
      case Status() => {
        reply(SomeObject.slowDBMethod)
      }
    }
  }

  case class Status()

一旦收到请求,就应该创建一个新的参与者来处理该请求。传递原始发件人,以便新创建的演员知道该向谁应答。

您似乎正在使用旧版本的Akka

我建议升级到0.10(将参与者和RS bean分开),然后可以使用LoadBalancer(和)来调节工作负载,或者利用WorkStealingDispatcher(和)


这有帮助吗?

虽然我意识到这个线程已经过时4个多月了,但值得注意的是,Akka有一个新的HTTP模块实现,可以有效地将请求传输到参与者。这种方法利用异步ServletAPI(也与Jetty continuations一起使用),使挂起的请求能够作为消息在系统中传递,并在任何时候恢复;例如,消除使用的需要!!触发参与者工作并在带注释的POJO中响应。同样,由于请求挂起在容器中,并且上下文尽可能快地转换为参与者,因此没有线程阻塞来处理响应或未来

今天可以用一种天真的方式重写上述示例:

class TestEndpoint extends Actor with Endpoint {
   def hook(uri:String) = uri == "/test"
   def provide(uri:String) = actorOf[TestService].start

   override def preStart = {
     ActorRegister.actorsFor[classOf[RootEndpoint]).head ! Endpoint.Attach(hook, provide)
   }

   def receive = handleHttpRequest
}

class TestService extends Actor {
   def receive = {

     case get:Get => 
       get.timeout(SomeObject.TimeoutInSeconds) // for example
       get.OK(SomeObject.slowDBMethod)

     case other:RequestMethod =>
      other.NotAllowed("Invalid method for this endpoint")
   }
}

在akka网站上可以找到更多文档:

尽管此线程很旧,但我想在混合中添加Spiffy(plug!):

什么是漂亮的?

漂亮的

  • 是用Scala编写的
  • 使用神奇的Akka库和演员进行缩放
  • 使用ServletAPI 3.0进行异步请求处理
  • 模块化(直接更换部件)
  • 使用DSL减少不需要的代码
  • 支持控制器周围的请求挂钩

Spiffy是一个使用Scala、Akka(Scala actor实现)和JavaServelet3.0API的web框架。它利用异步接口,旨在为web应用程序提供一个大规模并行和可扩展的环境。Spiffy的各种组件都基于这样一个想法,即它们需要是独立的极简模块,能够非常快速地完成少量工作,并将请求传递给管道中的下一个组件。在最后一个组件处理完请求后,它通过“完成”请求并将其发送回客户机来向servlet容器发送信号。

在“正常”的参与者情况下,我希望这会起作用。但是在我的例子中,我真的不能在添加的代码示例的status()方法中传递“sender”吗?我假设无论我在receive方法中做什么,只要status()方法还没有完成,参与者就不会准备好接受更多的REST请求。保持每个用户的参与者会话如何?这看起来很有希望。我将试用0.10。我找不到akka rest的0.10版本,至少在maven2存储库中找不到。我应该使用0.8版本吗?@Magnus看到我做了所有这些。升级到0.10并实现了负载平衡器。然而,我的RS bean似乎仍然按顺序处理请求。由于大多数请求都在等待缓慢的后端操作,因此新请求几乎总是被暂停。即使请求似乎由不同的线程处理,也会发生这种情况。日志条目见编辑问题。嘿,马格纳斯,这应该在阿克卡大师中解决。Jettys QueuedThreadPool出错。您可能希望查看Apache Bench,而不是按F5键,这是一个非常好的并发测试工具。
class TestEndpoint extends Actor with Endpoint {
   def hook(uri:String) = uri == "/test"
   def provide(uri:String) = actorOf[TestService].start

   override def preStart = {
     ActorRegister.actorsFor[classOf[RootEndpoint]).head ! Endpoint.Attach(hook, provide)
   }

   def receive = handleHttpRequest
}

class TestService extends Actor {
   def receive = {

     case get:Get => 
       get.timeout(SomeObject.TimeoutInSeconds) // for example
       get.OK(SomeObject.slowDBMethod)

     case other:RequestMethod =>
      other.NotAllowed("Invalid method for this endpoint")
   }
}