【问题标题】:Akka HTTP Code/Structural PatternsAkka HTTP 代码/结构模式
【发布时间】:2018-07-13 15:38:33
【问题描述】:

我刚开始使用 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
}

然后,在我的主服务器中,只需混合特征以自动获取演员和路线:

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

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

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

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

  1. 允许我在不同的包中分离路由逻辑,并最好将其与相应的参与者捆绑在一起。
  2. 使路由动态且可发现,而不是在启动时指定它们。

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

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

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

谢谢!

【问题讨论】:

    标签: scala akka akka-http akka-cluster


    【解决方案1】:

    使用 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 的根演员:

    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系统和根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 路由的最佳实践的看法。我的回答中没有涵盖的是如何动态发现路由,但老实说,我看不到这里的用例。通常你的系统应该有一些明确定义的端点。如果系统甚至不知道在启动时将服务哪些端点,用户如何知道他们可以与哪些端点通信?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-01
      • 2020-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多