0

我有一个 akka 演员,我想在该演员中使用一个简单的服务。该服务应使用客户端 api 的singleRequest 方法从本地网络获取某些内容。

我的演员:

package actor

import actor.WorkerActor._
import akka.actor.Actor
import service.HealthCheckService

import scala.concurrent.ExecutionContext

object WorkerActor {
  case object HealthCheck
}

class WorkerActor extends Actor {

  implicit val system = context.system
  implicit val ec: ExecutionContext = context.system.dispatcher

  val healthCheckService = new HealthCheckService()

  override def receive: Receive = {
    case HealthCheck => sender ! healthCheckService.execute()
  }
}

在这里,我还创建了一个 ActorSystem 和一个 ExecutionContext,以便我的服务可以使用它:

package service

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpRequest, HttpResponse}

import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Failure, Success}

class HealthCheckService(implicit ec: ExecutionContext, implicit val system: ActorSystem) {


  def execute() = {
    val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = "http://someRandom.url"))

    and do something with the response....
  }
}

如果我没有将 executionContext 传递到服务中,我会收到错误消息:

[error] Cannot find an implicit ExecutionContext. You might pass
[error] an (implicit ec: ExecutionContext) parameter to your method
[error] or import scala.concurrent.ExecutionContext.Implicits.global.

如果我没有将 actorsystem 传递到服务中,我会收到错误消息:

[error] could not find implicit value for parameter system: akka.actor.ActorSystem
[error] val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = "http://someRandom.url"))

问题:

  • Actor 应该如何正确使用服务?
  • 传递 ActorSystem 和 ExecutionContext 是否正确,为什么它不会在幕后发生?
4

1 回答 1

0

Http.apply签名是

def apply()(implicit system: ActorSystem): HttpExt

所以你需要ActorSystem隐式或显式地传递给它。我在服务中看不到任何需要 ExecutionContext 的东西,所以假设你FuturesingleRequest调用中得到了一些东西。任何方法Future都需要执行上下文。

所以代码是正确的,但可以简化一点:

class WorkerActor extends Actor {
  // you do not need to declare implicit val if you just need to pass it once
  val healthCheckService = new HealthCheckService(context.system)

  override def receive: Receive = {
    case HealthCheck => sender ! healthCheckService.execute()
  }
}

class HealthCheckService(implicit val system: ActorSystem) {
  // dispatcher is already implicit so you need just import it, not declare another val
  import system.dispatcher
  def execute() = {
    val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = "http://someRandom.url"))

    and do something with the response....
  }
}

此外,从您的服务代码中,我的印象是您以某种方式操纵未来,可能会添加等待(只要您的每个问题的服务并不真正需要ActorSystem),而不是使用 akka 并将消息从Future. 可能(作为您第一个问题的答案),您需要检查稍后使用singleRequest从链接到您在问题中添加的 akka-http 的演员的示例。

于 2018-02-18T19:03:49.893 回答