Akka:如何管理双重http请求?

时间:2016-08-29 14:18:44

标签: scala akka

在我的演员中,我在不同的地址有两个请求:

http.singleRequest(HttpRequest(uri = encodedUri).addHeader(Accept(MediaTypes.`application/json`)))

我需要这两个请求都返回一个值。作为正常的未来,我期待这样的事情:

val response: Future[SomeData] = for {
        r1 <- firstRequest
        r2 <- secondRequest
      } yield {
        // merge the results of these two responses
      }

      response onComplete {
        case Success(body) => sndr ! Something(body)
        case Failure(message) => BadRequest(message.toString)
      }

在文档的这一部分:

http://doc.akka.io/docs/akka/2.4/scala/http/client-side/request-level.html

建议使用pipeToself来管理单个请求,而不是使用原生onComplete/map/etc

如何在多个请求中应用该请求,例如我需要等待2个或更多个请求才能完成?

1 个答案:

答案 0 :(得分:3)

简单而直接的

val f1 = Future { //request1 }

val f2 = Future { //request2 }

val resultF = f1 zip f2 

resultF pipeTo self

当前演员将获得结果作为消息,消息将是元组(f1Result, f2Result)

如果结果resultF失败,则当前的actor获取包含在akka.actor.Status.Failure

中的失败消息

方法f1f2是独立期货

如果f2取决于f1使用flatMap

的值
 val resultF = f1.flatMap { f1Result => createF2(f1Result) }

 //alternatively we can use for comprehension

 resultF pipeTo self

示例

import akka.actor.Actor
import akka.actor.Status.Failure

import scala.concurrent.Future
import akka.pattern.pipe

object ManagerActor {
  case object Exec
}

class ManagerActor extends Actor {

  import ManagerActor._

  implicit val dispather = context.dispatcher

 override def receive: Receive = {
    case Exec =>

    val f1 = Future { 1 }

    val f2 = Future { 2 }

    val resultF = f1 zip f2

    resultF pipeTo self

   case result: (Int, Int) => //be careful about type erasure 
     println(s"""result:$result""")

   case Failure(th) =>
     println(s"""msg: ${th.getMessage}""")

   }
}

运行

object Main {
 def main(args: Array[String]): Unit = {
   val system = ActorSystem()
   val actor = system.actorOf(Props[ManagerActor])
   actor ! ManagerActor.Exec
   Thread.sleep(1000000)
 }
}

我们可以使用Future.sequence代替zip将此概括为任意数量的http请求。