使用ActorSystem内的Spray客户端实现路由

时间:2014-07-17 03:18:41

标签: scala routing akka actor spray

我有一个用于调用REST Web服务的Spray客户端。目前我正在创建此客户端的实例(使用new GeoSprayWebClient)[参见下面的代码]并在我的actor中重用它来发出REST请求。但是,单个服务实例无法处理所有负载。因此,我想介绍REST服务的副本。

我是Spray的新手,仍在努力学习基础知识。我的问题是

1)我知道Spray内部使用Akka演员。在这种特殊情况下,我可以为客户端实例获取ActorRef,以便我可以创建多个客户端ActorRef并使用它们来创建Akka路由器。 2)Spray客户端API是否提供支持我的用例的任何类型的路由功能?

 import akka.actor.ActorSystem
 import spray.client.pipelining._
 import spray.http._
 import scala.concurrent.Future


trait GeoWebClient {
  def get(url: String, params: Map[String, String]): Future[String]
}

class GeoSprayWebClient(implicit system: ActorSystem) extends GeoWebClient {

  import system.dispatcher

  // create a function from HttpRequest to a Future of HttpResponse
  val pipeline: HttpRequest => Future[HttpResponse] = sendReceive

  // create a function to send a GET request and receive a string response
  def get(path: String, params: Map[String, String]): Future[String] = {
    val uri = Uri(path) withQuery params
    val request = Get(uri)
    val futureResponse = pipeline(request)
    futureResponse.map(_.entity.asString)
  }
}

2 个答案:

答案 0 :(得分:0)

  1. 实现WebClientActor,它调用GeoSprayWebClient来完成您的工作。

  2. 创建路由器作为喷雾处理程序:

  3. val handler = context.actorOf( 道具[WebClientActor] .withRouter(RoundRobinRouter(5)),name =" handlerRouter")

    1. 向处理程序发送请求消息
    2. 通过这种方式,我们有5个客户端实例来做请求。

      我也是新手,但不确定是否符合您的目的。仅供参考。

      欢呼〜!

答案 1 :(得分:0)

基于this,我得到了ActorRef

def createHttpRESTClient(host: String, port: Int): ActorRef = {

      // execution context for future transformations below
      import system.dispatcher
      implicit val timeout: Timeout = 10 seconds

      val ref: Future[ActorRef] = for {
        Http.HostConnectorInfo(hostConnector: ActorRef, _) <- IO(Http) ? Http.HostConnectorSetup(host, port)
      }
      yield {
        hostConnector
      }
      //FIXME - TODO fix this it's really bad. However, We are going to create this only once when we create the actor, so I guess it's okay for now.
      Await.result(ref, 10 seconds)
    }

这就是我发送请求并使用ActorRef从服务获取响应的方式。

  def sendReq(text: String): Future[String] = {
    import spray.http._
    val params = Map(("key" -> text))
    val uri = Uri("/myservice") withQuery params
    val request = Get(uri)
    //send GET request using the "ask" pattern; the timeout
    //TODO - not sure if we can use tell instead of ask here ? 
    val response: Future[HttpResponse] = restSvrActorRef.ask(request).mapTo[HttpResponse]
    log.debug(s"done with sending a request to the REST service")
    response.map(_.entity.asString)
  }