当涉及在 akka http 上创建具有 60 多个 API 的 REST Web 服务时。我如何选择应该使用 akka 流还是使用 akka 演员?在他的帖子中,Jos 展示了在 akka http 上创建 API 的两种方法,但他没有展示我何时应该选择其中一种。
2 回答
这是一个困难的问题。显然,这两种方法都有效。所以在某种程度上,这是一个品味/熟悉的问题。所以接下来的一切都只是我个人的看法。
如果可能,我更喜欢使用 akka-stream,因为它具有更高级别的性质和类型安全性。但是这是否是一种可行的方法在很大程度上取决于 REST API 的任务。
阿卡流
如果您的 REST API 是一种服务,例如根据外部数据回答问题(例如货币汇率 API),则最好使用 akka-stream 来实现它。
akka-stream 更可取的另一个示例是某种数据库前端,其中 REST API 的任务是解析查询参数,将它们转换为数据库查询,执行查询并根据请求的内容类型转换结果由用户。在这两种情况下,数据流很容易映射到 akka-stream 原语。
演员
如果您的 API 允许查询和更新集群上的多个持久性参与者,那么使用参与者可能会更可取。在这种情况下,纯基于 actor 的解决方案或混合解决方案(使用 akka-stream 解析查询参数和翻译结果,其余部分使用 actor)可能更可取。
另一个基于参与者的解决方案可能更可取的示例是,如果您有一个 REST API 用于长时间运行的请求(例如 websockets),并且想要在集群上部署 REST API 本身的处理管道。我认为目前使用 akka-stream根本不可能实现这样的事情。
概括
总结一下:查看每个 API 的数据流,看看它是否清晰地映射到 akka-stream 提供的原语。如果是这种情况,请使用 akka-stream 实现它。否则,请使用参与者或混合解决方案来实施。
不要忘记期货!
我要对 Rudiger Klaehn 的好答案做的一个附录是还要考虑Future
. Futures 的可组合性和资源管理ExecutionContext
使 Futures 成为许多(如果不是大多数)情况的理想选择。
有一篇很棒的博客文章描述了 Future 何时是比 Actor 更好的选择。此外,Streams 提供的背压带来了相当大的开销。
仅仅因为您使用 akka-http 陷入困境并不意味着您的请求处理程序中的所有并发都必须限于 Actors 或 Streams。
路线
Route
在类型定义中固有地容纳 Futures :
type Route = (RequestContext) ⇒ Future[RouteResult]
因此,您可以仅使用函数和 Futures 将 Future 直接烘焙到您的 Route 中,而不使用 Directives:
val requestHandler : RequestContext => HttpResponse = ???
val route : Route =
(requestContext) => Future(requestHandler(requestContext)) map RouteResult.Complete
onComplete 指令
该onComplete
指令允许您在您的路线中“解开”未来:
val route =
get {
val future : Future[HttpResponse] = ???
onComplete(future) {
case Success(httpResponse) => complete(httpResponse)
case Failure(exception) => complete(InternalServerError -> exception.toString)
}
}