简体   繁体   English

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

[英]akka http: Akka streams vs actors to build a rest service

When it comes to creating a REST web service with 60+ API on akka http. 在akka http上创建一个包含60+ API的REST Web服务时。 How can I choose whether I should go with akka streams or akka actors? 如何选择是否应该选择akka流或akka演员? In his post , Jos shows two ways to create an API on akka http but he doesn't show when I should select one over the other. 在他的帖子中 ,乔斯展示了两种在akka http上创建API的方法,但他没有显示何时我应该选择一个而不是另一个。

This is a difficult question. 这是一个棘手的问题。 Obviously, both approaches work. 显然,这两种方法都有效。 So to a certain degree it is a matter of taste/familiarity. 所以在某种程度上这是一个品味/熟悉的问题。 So everything following now is just my personal opinion. 所以现在关注的一切只是我个人的意见。

When possible, I prefer using akka-stream due to its more high-level nature and type safety. 如果可能的话,我更喜欢使用akka-stream,因为它具有更高级别的性质和类型安全性。 But whether this is a viable approach depends very much on the task of the REST API. 但这是否是一种可行的方法在很大程度上取决于REST API的任务。

Akka-stream 阿卡流

If your REST API is a service that eg answers questions based on external data (eg a currency exchange rate API), it is preferable to implement it using akka-stream. 如果您的REST API是一种服务,例如基于外部数据(例如货币兑换率API)回答问题,则最好使用akka-stream实现它。

Another example where akka-stream would be preferable would be some kind of database frontend where the task of the REST API is to parse query parameters, translate them into a DB query, execute the query and translate the result according to the content-type requested by the user. akka-stream最好的另一个例子是某种数据库前端,其中REST API的任务是解析查询参数,将它们转换为数据库查询,执行查询并根据请求的内容类型转换结果由用户。 In both cases, the data flow maps easily to akka-stream primitives. 在这两种情况下,数据流都很容易映射到akka-stream原语。

Actors 演员

An example where using actors would be preferable might be if your API allows querying and updating a number of persistent actors on a cluster. 如果您的API允许查询和更新群集上的多个持久性actor,则可以使用actor更好的示例。 In that case either a pure actor-based solution or a mixed solution (parsing query parameters and translating results using akka-stream, do the rest using actors) might be preferable. 在这种情况下,基于纯粹的基于actor的解决方案或混合解决方案(解析查询参数和使用akka-stream翻译结果,使用actor执行其余操作)可能更可取。

Another example where an actor-based solution might be preferable would be if you have a REST API for long-running requests (eg websockets), and want to deploy the processing pipeline of the REST API itself on a cluster. 基于actor的解决方案可能更受欢迎的另一个例子是,如果您有长期运行请求的REST API(例如websockets),并希望在集群上部署REST API本身的处理管道。 I don't think something like this is currently possible at all using akka-stream. 我不认为这样的事情目前是不可能使用阿卡流。

Summary 摘要

So to summarize: look at the data flow of each API and see if it maps cleanly to the primitives offered by akka-stream. 总结一下:查看每个API的数据流,看看它是否干净地映射到akka-stream提供的原语。 If this is the case, implement it using akka-stream. 如果是这种情况,请使用akka-stream实现它。 Otherwise, implement using actors or a mixed solution. 否则,使用actor或混合解决方案实现。

Don't Forget Futures! 不要忘记期货!

One addendum I would make to Rudiger Klaehn's fine answer is to also consider the use case of a Future . 我对Rudiger Klaehn的一个好的答案是一个附录,也是考虑Future的用例。 The composability of Futures and resource management of ExecutionContext make Futures ideal for many, if not most, situations. Futures的可组合性和ExecutionContext资源管理使Futures成为许多(如果不是大多数)情况的理想选择。

There is an excellent blog post describing when Futures are a better choice than Actors. 有一篇很棒的博客文章描述了Futures比Actors更好的选择。 Further, the back-pressure provided by Streams comes with some pretty hefty overhead . 此外,Streams提供的背压带来了一些相当大的开销

Just because you're down the rabbit hole using akka-http does not mean all concurrency within your request handler has to be confined to Actors or Streams. 仅仅因为你使用akka-http陷入了兔子洞并不意味着你的请求处理程序中的所有并发都必须局限于Actors或Streams。

Route 路线

Route inherently accomodates Futures in the type definition : Route固有地适应类型定义中的期货:

type Route = (RequestContext) ⇒ Future[RouteResult]

Therefore you can bake a Future directly into your Route using only functions and Futures, no Directives: 因此,您可以仅使用函数和期货直接将Future烘焙到您的Route中,无需指令:

val requestHandler : RequestContext => HttpResponse = ???

val route : Route = 
  (requestContext) => Future(requestHandler(requestContext)) map RouteResult.Complete

onComplete Directive onComplete指令

The onComplete Directive allows you to "unwrap" a Future within your Route: onComplete Directive允许您在路线中“展开”未来:

val route = 
  get {

    val future : Future[HttpResponse] = ???

    onComplete(future) {
      case Success(httpResponse) => complete(httpResponse)
      case Failure(exception)    => complete(InternalServerError -> exception.toString)
    }
  } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM