Akka HTTP代码/结构模式

时间:2017-03-05 23:51:28

标签: scala akka akka-http akka-cluster

我刚刚开始使用Akka Http(和Scala),并想知道是否有任何明确定义的模式来构建Akka代码。特别是,我正在寻找动态组合/聚合路由的结构模式。特别是,我正在寻找类似于以下伪代码的解决方案:

trait MyActor extends Actor {
  val myRouter: ActorRef = context.actorOf(FromConfig.props(Props[MyWorker]), "Worker")
val myRoute = .... //route definition for this trait
}



trait MySecondActor extends Actor {
  val mySecondRouter: ActorRef = context.actorOf(FromConfig.props(Props[MySecondWorker]), "SecondWorker")
    val myRoute = .... //route definition for this trait
}

然后,在我的主服务器中混合使用特征来自动获取actor和路由:

class HttpServer extends SomeTrait with MyActor with MySecondActor {
.....
.....
 }

上述模式存在一些明显的问题,包括:

  1. 所有特征都继承自Actor,然后混合到同一个类中 - 不确定最终行为是什么。
  2. HttpServer类本身成为一个actor,无法通过new HttpServer()实例化
  3. 路线没有连接。
  4. 我正在寻找的是一种模式:

    1. 允许我将各种包中的路由逻辑分开,最好将其与相应的actor捆绑在一起。
    2. 使路由动态且可被发现,而不是在引导时指定它们。
    3. 我在StackOverflow上遇到了以下两个,但是想知道是否有更好的方法和明确定义的模式:

      1. akka-http with multiple route configurations(这不是真正的动态)

      2. How to aggregate akka-http routes using a trait?(使用反思的旧问题)

      3. 谢谢!

1 个答案:

答案 0 :(得分:5)

使用akka-http时,您通常不需要演员来实施路由。 Actor通常仅用于异步访问业务逻辑。让我举例说明如何使用预定义的路由构建代码。这是我从Heiko Seeberger学到的模式。

首先创建一个创建路线的对象:

object Api {

  def route: Route = {
    import import akka.http.scaladsl.server.Directives._

    pathSingleSlash {
      get {
        complete(StatusCodes.OK)
      }
    }
  }
}

如果您需要演员来访问您的业务逻辑,您可以将其作为参数传递给route方法。在请求处理期间与actor交互时,请记住使用ask pattern

比你创建一个创建你的Api的Root actor:

final class Root extends Actor with ActorLogging {

  Http(context.system)
    .bindAndHandle(Api.route, "0.0.0.0", 8000)
    .pipeTo(self)

  override def receive: Receive = {
    case s: ServerBinding =>
      log.info(s"Listening to ${s.localAddress}")
      context.become(Actor.emptyBehavior)
    case Status.Failure(t) =>
      log.error(t, "Error binding to network interface")
      context.stop(self)
  }
}

最后,您需要一些主要方法来创建actor系统和Root actor:

object Main {

  def main(args: Array[String]): Unit = {
    val system = ActorSystem("user-api")
    system.actorOf(Props(new Root))

    Await.ready(system.whenTerminated, Duration.Inf)
  }
}

所以这将是我对定义akka-http路由的最佳实践的看法。我的答案中没有涉及的是如何动态发现路由,但说实话,我在这里看不到用例。通常,您的系统应该有一些明确定义的端点。如果系统不知道它将在启动时服务哪些端点,用户将如何知道他们可以与哪些端点通信?