Akka框架的最佳使用案例是什么?

623

我听说过很多有关 Akka 框架 (Java/Scala 服务平台) 的赞扬,但到目前为止还没有看到许多实际使用案例。所以我很想听听开发者成功使用它的事情。

只有一个限制:请不要包括编写聊天服务器的情况。(为什么?因为这已经被过度使用作为许多类似事物的示例)


10
“是不是先找到问题再寻找解决方案比已经有了解决方案再去寻找适用的问题更容易呢?” “我猜想,与使用 RMI 相比,Akka 及其 Actor 看起来更容易/简单编写代码。” - Kennet
75
好的,如果我有具体问题需要解决。我并不是在寻找“借口来使用Akka”,但我对学习更多内容很感兴趣。这可能有助于解决未来的问题,但主要是为了持续学习的过程。 - StaxMan
有一个相关的问题,但是关于将AKKA应用于现有应用程序以及一些用例:https://dev59.com/5WQn5IYBdhLWcg3wvpUV#16674690 - ses
2
Akka是一种比JMS或MQ风格的分布式消息队列系统更好的解决方案。这是我最近问过的确切同样的问题的最佳理解方式:“我知道如何使用它并看到了我可以使用它的地方,但我看不出这将提供真正的优势。” Akka背后的核心设计假设比JMS/MQ要好得多,特别是关于进程隔离、无锁设计和重试/故障处理方面。其次,API比JMS/MQ工具更加优雅。 - user2684301
2
@user2684301 嗯,我觉得那个回答有点不公平,像是在比较苹果和橙子。MQ(消息队列)是逻辑上的简单构建块,比起 Akka 来做的事情要少得多,我不会把它们并排比较。但是如果我把它理解为“与使用 JMS 构建的分布式系统相比,以声明方式编写”,那么就更有意义了。 - StaxMan
显示剩余2条评论
12个回答

331

我已经在两个实际项目中成功地使用了Akka。这两个项目都是关于近实时的交通信息领域(交通指高速公路上的汽车),分布在多个节点上,集成了几个参与方之间的消息,并拥有可靠的后端系统。目前我还不能透露客户的具体信息,等到获得许可后再添加为参考资料。

Akka在这些项目中发挥了很大的作用,尽管我们在0.7版本开始使用它。(顺便说一句,我们使用的是Scala)

其中一个重要优点是可以轻松地将Actor和Message组合成一个系统,几乎没有任何样板代码,它的可扩展性非常好,而且不需要手动编写复杂的线程,你甚至可以免费获得对象之间异步消息传递的能力。

它非常擅长建模任何类型的异步消息处理。我更喜欢使用这种风格编写任何类型的(网络)服务系统,而不是其他风格。(你是否曾经尝试过使用JAX-WS编写异步Web服务(服务器端)?那真的是太麻烦了)。因此,我会说任何一个不想因为某个组件出现问题而导致整个系统挂掉的系统,都可以使用Akka。它非常稳定,而且"让它崩溃+监管者解决方案"的方法可以很好地解决故障问题。一切都很容易设置编程和单元测试。

此外还有优秀的附加模块。Camel模块可以很好地与Akka结合,实现可配置终端点的异步服务的轻松开发。

我对这个框架非常满意,它正在成为我们构建连接系统的事实标准。


15
你认为相比于使用消息传递后端(例如ActiveMQ)进行消息传递,采用这种方法的好处是什么? - magiconair
27
MQ产品的用途确实不同。它们提供不同的保证和非常不同的性能。MQ产品需要大量设置,您不会像使用对象一样在该产品中使用队列。在Akka中,Actor是一等公民,您可以随意使用它们,类似于使用对象,因此在编程模型和设置方面减少了很多开销。您更多地使用MQ产品与其他外部系统集成,而不是构建系统内部,这是您将使用Actor的地方。 - Raymond Roestenburg
27
DBP案例研究的新网址是http://downloads.typesafe.com/website/casestudies/Dutch-Border-Police-Case-Study-v1.3.pdf。 - Bas
2
基于@RaymondRoestenburg关于MQ系统和替代方案的讨论,例如RabbitMQ是建立在基于Actor的编程语言Erlang之上。这是一种思考Actor和MQ之间关系(以及区别)的方式。同时,Apache Spark既不是Worker-and-Queue也不是Actor-based,但可以与Akka一起使用:Typesafe演示了如何使用Spark Streaming与Akka(http://www.typesafe.com/activator/template/spark-streaming-scala-akka)。 - floer32
6
@RaymondRoestenburg,你没有提到Actor模型本身会促使代码结构像意大利面一样混乱。你写的《Akka in Action》这本书是最好的说明。书中的代码示例处理的故事非常基础,但是从代码中理解和跟踪工作流程非常困难。相关问题是,Akka代码将以最具侵入性的方式永久地遍布于你的业务逻辑中,比任何其他非Actor框架都要多得多。简单地说,如果不将其分解成不同的部分,就无法编写基本的工作流程。 - rapt

227

免责声明:我是Akka的PO

Akka除了提供更加容易理解和正确性的并发编程方案(包括Actor、Agent、Dataflow Concurrency等),同时还提供STM的并发控制。

以下是一些可能需要考虑的使用场景:

  1. 交易处理(在线游戏、金融、统计、博彩、社交媒体、电信等)
    • 可扩展,高可用性,容错性
  2. 服务后端(任何行业,任何应用程序)
    • 支持REST、SOAP、cometd等服务接口
    • 作为消息中心/集成层
    • 可扩展,高可用性,容错性
  3. 插入式并发/并行性(任何应用程序)
    • 正确性
    • 简单易用且易于理解
    • 只需将jar包添加到现有的JVM项目中(使用Scala、Java、Groovy或JRuby)
  4. 批量处理(任何行业)
    • 使用Camel集成批量数据源
    • Actors分割并征服批量工作负载
  5. 通信中心(电信、网络媒体、移动媒体)
    • 可扩展,高可用性,容错性
  6. 游戏服务器(在线游戏、博彩)
    • 可扩展,高可用性,容错性
  7. 商业智能/数据挖掘/通用计算
    • 可扩展,高可用性,容错性
  8. 在此插入其他适用场景

12
我了解期货和STM的好处,但是我没有找到演员的好用例。对于游戏或投注服务器,使用演员与在负载均衡器后面使用多个应用程序服务器相比有什么优势? - Martin Konicek
8
@ViktorKlang 提到的 POs 不等同于技术主管。它们虽然一起工作,但是职责不同。 - taylorcressy
我无法理解Akka如何用于商业智能/数据挖掘/通用计算等领域。 - JustTry
我无法理解Akka如何用于BI/数据挖掘/通用计算。 - undefined

80
我们使用它的一个例子是在借记/信用卡交易的优先队列上。我们有数百万个这样的交易,工作的努力取决于输入字符串类型。如果交易是CHECK类型,则我们几乎没有处理,但如果是销售点,则需要执行许多操作,例如与元数据(类别、标签、标签等)合并并提供服务(电子邮件/短信警报、欺诈检测、低资金余额等)。根据输入类型,我们组成具有各种特征(称为mixin)的类来处理工作,然后执行工作。所有这些作业都以实时模式从不同的金融机构进入同一队列。一旦数据被清理,它就会被发送到不同的数据存储区进行持久化、分析或推送到套接字连接或Lift彗星演员。工作演员不断自我负载平衡工作,以便我们可以尽快处理数据。我们还可以捕捉额外的服务、持久性模型和用于关键决策点。
在JVM上的Erlang OTP风格的消息传递是开发基于现有库和应用程序服务器的实时系统的绝佳选择。
Akka允许您像传统的一样进行消息传递,但速度更快!它还为您提供了框架中管理大量actor池、远程节点和容错所需的工具。

1
那么可以说这是一些长延迟请求的情况,单线程每个请求的处理能力不会很好地扩展,这样说公平吗? - StaxMan
7
我认为演员编程的重要部分是消息流。一旦你开始以没有副作用的数据流的概念化方式,你就希望每个节点上发生尽可能多的数据流。这与高性能计算非常不同,因为在高性能计算中,你有半同质的任务,不发送消息并且需要很长时间来处理。我认为基于演员的斐波那契实现是一个非常局限的例子,因为它只展示了使用演员的方法而不是演员的应用场景。考虑事件驱动的架构来解决问题。 - Wade Arnold
4
事件驱动架构是解决问题的一种不同思考方式。如果你在考虑使用Akka进行编码,那么阅读Manning出版社的《Erlang OTP实战指南》是值得的。Akka中很多结构都受到了Erlang OTP的影响,这本书会告诉你为什么Jonas Boner会以他的方式构建Akka API的原则。Akka是你所站立的巨大山峰!如果你的Actor在状态变化时是持久的,那么你真的需要每秒写入10,000次吗? - Wade Arnold
8
Wade,你们是如何处理消息保证的?你提到了(电子邮件/短信提醒、欺诈检测、低余额等),我假设这些可能会发送到远程参与者?那么你们是如何确保这些操作实际发生的呢?如果节点在处理欺诈警报时失败了怎么办?它永远消失了吗?你们有一个最终一致性系统来清理它吗?谢谢! - James
2
很好的问题,詹姆斯。显然,它适用于不需要紧急回复的系统中。例如,您可以处理信用卡账单;计算;发送电子邮件等。我真的很想知道当需要回复时如何处理这些事务。最后,如果来自外部(互联网用户;呼叫中心代表等)的请求,他或她会等待回复。我如何确保子任务(异步执行)在xa事务中执行,以便我可以返回回复? - Kaan Yy
显示剩余3条评论

47

我们使用Akka异步处理REST调用 - 与基于Netty的异步Web服务器一起,与传统的每个用户请求模型相比,可以实现每个节点/服务器服务的用户数量提高10倍。

告诉你的老板,你的AWS托管账单将降低10倍,这是一个不需要思考的选择!嘘...不要告诉亚马逊... :)


4
我忘了提到Akka Futures的单子特性,这导致编写更干净的并行代码,节省了数千行代码维护成本... - piotrga
8
我假设电话是高延迟、低吞吐量的?就像给其他服务器打电话,等待响应(代理)一样? - StaxMan

39

我们在一项大规模电信项目中使用Akka(遗憾的是我无法透露太多细节)。Akka actors被部署并通过web应用程序远程访问。通过这种方式,我们采用基于Google protobuffer的简化RPC模型,并使用Akka Futures实现并行性。到目前为止,这个模型的表现非常出色。需要注意的一点是:我们正在使用Java API。


能否请您再详细说明一下?据我所知,Futures 无法通过网络(序列化)发送。您是使用大量的 Futures 和少量的 Actors,还是两者混合使用呢?您是否使用 protobuf 进行所有的序列化,并将其作为消息发送给 Actors? - Aktau
这似乎可以很容易地在没有Akka的情况下处理。 - Erik Kaplun
1
TDC是Fiaddesio案例中的电信公司。 - Roman Kagan

38

如果将聊天服务器抽象到更高一层,则会得到答案。

Akka 提供了一种类似于 Erlang 的 "让它崩溃" 思想的消息系统。

因此,以下是需要不同耐久性和可靠性的消息传递的示例:

  • 聊天服务器
  • 大型多人在线游戏的网络层
  • 金融数据泵
  • iPhone/移动应用程序的通知系统
  • REST 服务器
  • 或许类似于 WebMachine(猜测)的某些东西

Akka 的好处在于提供了多种持久化、STM 实现、REST 服务器和容错选择。

不要因为聊天服务器的例子而感到烦恼,把它看作是某个解决方案的一个示例。

尽管他们有出色的文档,但我感觉缺少的是这个确切的问题、用例和示例。请记住这些示例都是非平凡的。

(只有观看视频和使用源代码的经验,我没有使用 akka 实现过任何东西。)


2
谢谢 - 我并不是说聊天服务器一定不好,只是我想要更多的补充例子;这样更容易得到潜力的更好的想法。 - StaxMan
想知道REST服务器在这里如何适用?你是在提到Node.js风格的异步服务器上下文中吗?感谢分享示例用例。我发现它们很有用。 - software.wikipedia

25

我们在工作中的几个项目中都使用了Akka框架,其中最有趣的一个涉及到车辆碰撞修复。主要是在英国,但现在正在扩展到美国、亚洲、澳大利亚和欧洲。

使用Actor机制确保提供实时的碰撞修复信息,以便对车辆进行安全和成本效益的修复。

对于Akka框架,真正的问题是“你不能用Akka做什么”。它能够与强大的框架集成,具有强大的抽象能力和所有的容错特性,使其成为一个非常全面的工具包。


如果你必须选择,你最喜欢哪个方面?现有的其他框架集成、自动容错,还是其他什么? - StaxMan
6
就个人而言,我最喜欢Akka带来的是更高层次的抽象化。从企业角度看,它的集成能力也很吸引人。使用Akka既能满足商业需求,也能带来乐趣 :-) - rossputin
您能详细说明消息流程吗?用户是否在修车店并输入有关碰撞的详细信息到http表单中,然后将数据发送到服务器。这会创建一个由Akka处理的消息吗?用这条消息做什么?提取输入的信息以查询数据库,然后将回复排队以将其发送回Web前端? - surfmuggle

25

您可以使用Akka完成多种不同的任务。

我曾在一个网站上工作,将技术栈迁移到了Scala和Akka。我们几乎用它来处理网站上发生的所有事情。即使您可能认为聊天示例很糟糕,但它们本质上都是相同的:

  • 网站上的实时更新(例如视图、赞等)
  • 显示实时用户评论
  • 通知服务
  • 搜索和所有其他类型的服务

特别是实时更新很容易实现,因为它们归结为聊天示例。服务部分是另一个有趣的主题,因为您可以选择使用远程actor,即使您的应用程序没有集群,也可以轻松地在不同的计算机上部署。

我还在使用Akka开发PCB自动布线应用程序,想要实现从笔记本电脑到数据中心的可扩展性。给予其更多的能量,结果会更好。如果您尝试使用常规并发,则这非常难以实现,因为Akka还提供了位置透明度。

目前,我正在构建一个仅使用actor的Web框架作为业余项目。再次强调,其优点是可以将可扩展性从单台机器扩展到整个机群。此外,使用消息驱动的方法使您的软件从一开始就面向服务。您拥有所有这些美妙的组件,彼此交谈但不必然知道彼此的存在,共存于同一台机器上,甚至不在同一个数据中心。

自Google Reader关闭以来,我开始使用Akka构建RSS阅读器。对我而言,这一切都与封装的服务有关。总之:您应该首先采用actor模型,并且Akka是一个非常可靠的框架,可以帮助您实现它并获得许多好处。


你好Joe,能否解释一下如何使用消息来更新网站? 是否有一个适用于内容作者的系统:他创建了新文章并保存后,是否会生成一条消息发送到多台处理传入流量的服务器? 每个服务器尽快处理更新消息。然后每个新的浏览器请求都会得到页面的更新版本吗?谢谢 - surfmuggle

20

我尝试使用Akka(Java api)进行测试。我试图比较Akka的基于actor的并发模型与普通Java并发模型(java.util.concurrent类)。

用例是一个简单的规范化映射减少实现字符计数。数据集是一组随机生成的字符串(长度为400个字符),并计算其中元音字母的数量。

对于Akka,我使用了BalancedDispatcher(用于在线程之间进行负载平衡)和RoundRobinRouter(用于限制函数actors的数量)。对于Java,我使用了简单的fork join技术(没有实现任何工作窃取算法),它将分叉的map/reduce执行和join结果。中间结果保存在阻塞队列中,以使连接尽可能并行。也许,如果我没有弄错的话,这在某种程度上会模仿Akka actors的"邮箱"概念,它们接收消息。

观察: 在中等负载(~50000个字符串输入)下,结果是可比较的,在不同的迭代中略有不同。然而,当我将负载增加到~100000时,它会挂起Java解决方案。在这种情况下,我将Java解决方案配置为20-30个线程,并在所有迭代中失败。

将负载增加到1000000时,对于Akka来说也是致命的。我可以与任何感兴趣的人分享代码进行交叉检查。

所以对我来说,似乎Akka比传统的Java多线程解决方案更好地扩展了。可能的原因是Scala在幕后的魔术。

如果我可以将问题域建模为事件驱动的消息传递问题,我认为Akka是JVM的一个不错的选择。

测试执行于: Java版本:1.6 IDE: Eclipse 3.7 Windows Vista 32位. 3GB内存。Intel Core i5处理器,2.5 GHz时钟速度

请注意,用于测试的问题域可能存在争议,我尽量公平。


3
我可以与任何有兴趣进行交叉检查的人分享代码。如果您不介意,我想这样做。 - n1r3
3
我也想要代码,能否提供一个 Github 链接? - Gautam
感谢您的关注。不幸的是,我在设置GitHub仓库时遇到了一些问题。如果您可以给我您的电子邮件地址,我可以将源代码发送给您。再次很抱歉晚回复! - sutanu dalui
@sutanudalui,你还有那段代码吗?如果有的话,我可以分享我的电子邮件地址。 - Jay

18

我们正在使用带有其camel插件的akka来分布式处理twimpact.com的分析和趋势处理。我们需要每秒处理50到1000条消息。除了使用camel进行多节点处理外,还可用于在单个处理器上将工作分配给多个工作者以实现最大性能。效果相当不错,但需要一些处理拥塞的理解。


你也在使用Akka的容错机制吗? - Erik Kaplun
如果您可以访问Spark集群,那么使用Spark Streaming如何? - skjagini

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接