akka http:Akka 流与演员建立休息服务

Posted

技术标签:

【中文标题】akka http:Akka 流与演员建立休息服务【英文标题】:akka http: Akka streams vs actors to build a rest service 【发布时间】:2016-02-05 20:53:06 【问题描述】:

当谈到在 akka http 上创建具有 60 多个 API 的 REST Web 服务时。我如何选择应该使用 akka 流还是使用 akka 演员? 在他的post 中,Jos 展示了两种在 akka http 上创建 API 的方法,但他没有说明我应该何时选择其中一种。

【问题讨论】:

【参考方案1】:

这是一个难题。显然,这两种方法都有效。所以在某种程度上,这是一个品味/熟悉的问题。所以接下来的一切都只是我个人的看法。

如果可能,我更喜欢使用 akka-stream,因为它具有更高级别的性质和类型安全性。但这是否是一种可行的方法在很大程度上取决于 REST API 的任务。

Akka 流

如果您的 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 实现它。否则,请使用演员或混合解决方案实施。

【讨论】:

感谢 Rüdiger 的明确回答。我不喜欢将两者混合在一起,因为要获得背压,您需要依赖发布者/订阅者模型来处理您的演员。如果您想将请求向下发送到参与者层次结构,这会迫使您严重依赖 ask 模式而不是 tell。考虑到新参与者的微不足道的成本,每个请求的参与者模式很有价值。我还看到流作为底层子服务的聚合器工作得非常好,可以轻松地对子 API 进行分组。当您为 # 请求应该最少的移动设备进行开发时,这一点尤为重要。你怎么看? 说实话,我尽量使用akka-stream,只有在有特殊部署或其他需求时才使用原始actors。我认为很多用例都很好地映射到 akka-stream。 太棒了!顺便说一句,您能否提供一个简单的用例:“如果您的 API 允许查询和更新集群上的多个持久性参与者,那么参与者可能会更可取。”【参考方案2】:

别忘了期货!

我要对 Rudiger Klaehn 的好答案做的一个附录是还要考虑 Future 的用例。 Futures 的可组合性和 ExecutionContext 的资源管理使 Futures 成为许多(如果不是大多数)情况的理想选择。

有一个很好的blog post 描述了Futures 何时是比Actors 更好的选择。此外,Streams 提供的背压带来了相当大的overhead。

仅仅因为您使用 akka-http 陷入困境并不意味着您的请求处理程序中的所有并发都必须限制在 Actor 或 Streams 中。

路线

Route 在type definition 中固有地容纳期货:

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)
    
   

【讨论】:

以上是关于akka http:Akka 流与演员建立休息服务的主要内容,如果未能解决你的问题,请参考以下文章

如何在非对称系统中将对象发送到远程 akka 演员

Akka - 你应该创建多少个actor实例?

如何从演员本身中获取 Akka 演员的名字?

Java Akka Actor 和流

每个数据库实体一个 Akka 演员?

如何在akka中扩展超级演员的行为