Akka HTTP代码/结构模式

Moj*_*ojo 3 scala akka akka-cluster akka-http

我刚刚开始使用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
}
Run Code Online (Sandbox Code Playgroud)

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

class HttpServer extends SomeTrait with MyActor with MySecondActor {
.....
.....
 }
Run Code Online (Sandbox Code Playgroud)

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

  1. 所有特征都继承自Actor,然后混合到同一个类中 - 不确定最终行为是什么.
  2. HttpServer类本身成为一个actor,无法实例化 new HttpServer()
  3. 路线没有连接.

我正在寻找的是一种模式:

  1. 允许我在各种包中分离路由逻辑,并且最好将它与相应的actor捆绑在一起.
  2. 使路由动态且可发现,而不是在引导时指定它们.

我在StackOverflow上遇到了以下两个,但是想知道是否有更好的方法和明确定义的模式:

  1. 具有多个路由配置的akka​​-http(这不是真正的动态)

  2. 如何使用特征聚合akka-http路由?(使用反射的旧问题)

谢谢!

bri*_*ter 5

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

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

object Api {

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

    pathSingleSlash {
      get {
        complete(StatusCodes.OK)
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

比你创建一个创建你的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)
  }
}
Run Code Online (Sandbox Code Playgroud)

最后,您需要一些主要方法来创建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)
  }
}
Run Code Online (Sandbox Code Playgroud)

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