当涉及到使用akka http创建60多个API的REST web服务时,我该如何选择是使用akka streams还是akka actors?Jos在他的文章中展示了两种在akka http上创建API的方法,但他没有说明我应该在何时选择其中一种方式。
当涉及到使用akka http创建60多个API的REST web服务时,我该如何选择是使用akka streams还是akka actors?Jos在他的文章中展示了两种在akka http上创建API的方法,但他没有说明我应该在何时选择其中一种方式。
这是一个很难回答的问题。显然,两种方法都可行。因此在某种程度上,这是一种品味/熟悉度的问题。因此,接下来的所有内容都只代表我的个人观点。
如果可能的话,我更喜欢使用akka-stream,因为它具有更高级别的特性和类型安全性。但是否这种方法适用取决于REST API任务。
如果您的REST API是一种根据外部数据(例如货币汇率API)回答问题的服务,则最好使用akka-stream实现。
另一个akka-stream更适合的示例是某种数据库前端,其中REST API的任务是解析查询参数,将它们转换为DB查询,执行查询并根据用户请求的内容类型转换结果。在这两种情况下,数据流易于映射到akka-stream原语。
使用actors更适合的示例可能是,如果您的API允许在集群上查询和更新多个持久actors。在这种情况下,纯基于actor的解决方案或混合解决方案(使用akka-stream解析查询参数和转换结果,其余使用actors)可能更适合。
另一个使用基于actor的解决方案更合适的示例是,如果您有一个REST API用于长时间运行的请求(例如Websockets),并且希望将REST API本身的处理流水线部署在集群上。我认为使用akka-stream目前根本无法实现这种情况。
因此,总之:查看每个API的数据流,并查看它是否可以干净地映射到akka-stream提供的原语。如果是这种情况,请使用akka-stream实现。否则,使用actors或混合解决方案进行实现。
我想对Rudiger Klaehn的回答进行补充,考虑到Future
的使用情况。 Futures的可组合性和ExecutionContext
的资源管理使得Futures在许多情况下都是理想的选择。
有一篇优秀的博客文章描述了何时使用Futures比使用Actors更好。此外,流提供的反压力带来了相当大的开销。
仅仅因为你在使用akka-http并不意味着你的请求处理程序中所有的并发都必须限制在Actors或Streams中。
路由(Route)
Route
在类型定义中天然地支持Futures:
type Route = (RequestContext) ⇒ Future[RouteResult]
val requestHandler : RequestContext => HttpResponse = ???
val route : Route =
(requestContext) => Future(requestHandler(requestContext)) map RouteResult.Complete
onComplete指令
onComplete
指令允许你在Route中“解包”一个Future:
val route =
get {
val future : Future[HttpResponse] = ???
onComplete(future) {
case Success(httpResponse) => complete(httpResponse)
case Failure(exception) => complete(InternalServerError -> exception.toString)
}
}