如何在akka actor中使用akka-http cachedHostConnectionPool?

时间:2016-02-03 02:32:52

标签: scala akka akka-http

akka http文档在high level client request API documentation中提到我们不应该在演员的Future中使用访问actor状态表单。

相反,这应该是使用的模式:

import akka.actor.Actor
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.stream.scaladsl.ImplicitMaterializer

class Myself extends Actor
  with ImplicitMaterializer
  with ActorLogging {

  import akka.pattern.pipe
  import context.dispatcher

  val http = Http(context.system)

  override def preStart() = {
    http.singleRequest(HttpRequest(uri = "http://akka.io"))
      .pipeTo(self)
  }

  def receive = {
    case HttpResponse(StatusCodes.OK, headers, entity, _) =>
      log.info("Got response, body: " + entity.dataBytes.runFold(ByteString(""))(_ ++ _))
    case HttpResponse(code, _, _, _) =>
      log.info("Request failed, response code: " + code)
  }

}

使用cachedHostConnectionPool时我们应该做类似的事情吗?

例如:

import akka.actor.Actor
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.stream.scaladsl.ImplicitMaterializer

class Myself extends Actor
  with ImplicitMaterializer
  with ActorLogging {

  import akka.pattern.pipe
  import context.dispatcher

  var state = 10
  val http = Http(context.system)
  val pool = http.cachedHostConnectionPoolTls[Int](apiEndpoint.authority.host.toString())

  override def preStart() = {
    Source.single(HttpRequest(uri = "http://akka.io") -> 42)
      .via(poolClientFlow)
      .runWith(Sink.head)
      .pipeTo(self)
  }

  def receive = {
    case (res, ref) => ref match {
      case 42 => state -= 1 // Do something with the response 
    }
  }
}

如果是这样,为什么我们需要呢?无法在doc中找到解释 如果没有,那么正确的模式是什么?

谢谢

1 个答案:

答案 0 :(得分:1)

正如我的评论中所提到的,如果你需要改变actor的内部状态,你应该使用pipeToFuture的结果发送给自己进行处理。如果你不这样做,你就有可能遇到同时修改内部状态的问题而失去使用actor的好处。 Future的完成后逻辑将不会在actor的邮箱处理的上下文中执行,因此可能与邮箱中的邮件同时执行,从而导致潜在的并发性问题。这就是为什么如果你需要在Future完成它之后需要改变状态,建议他自行管理。

现在,如果之后没有经理状态,那么您不必使用pipeTo作为同时修改状态不会成为问题。