- Akka实战:快速构建高可用分布式应用
- 杜云飞
- 1927字
- 2025-04-04 08:24:03
第1章 认识Akka
打开本书第一章,你或许已经迫不及待地想体验一下“指尖”上的Akka,撸起袖子手起刀落地写下第一个例子:Hello World。别急,在选择(或学习)一种技术前,理解why比how可能更加重要,而了解基本的背景非常有助于我们理解why,即:我们为什么选择并相信它?
本章主要介绍Akka框架的技术背景,应用场景以及架构体系!
1.1 Akka简介
当今社会,一方面,人们越来越享受互联网带来的种种便利,同时也对互联网产品有了更高的要求,比如更快的响应速度和更稳定的服务;另一方面,互联网产品在不断发展的过程中也面临着非常多的技术挑战,比如服务化、分布式、并行计算等,那么,Akka在其中的哪些领域可以一展身手呢?
1.1.1 技术背景
在产品的早期阶段,由于用户量小,业务也比较单一,在开发时大多采用集中式的架构。在该架构下,工程师可以快速地进行产品迭代,而且由于此时的Bug潜伏期比较短,并且容易查找,整个项目的质量都处于可控状态。随着业务的发展,系统功能不断升级,产品逐渐变得复杂,新的开发需求也接踵而至,工程师除了要“如履薄冰”地添加新的功能,还要疲于应付系统潜在的Bug(如图1-1所示),当这种情况持续一段时间后,系统会变得更加臃肿不堪且难以维护,工程师们也会在此时滋生更多抱怨,不利于团队稳定。

图1-1 集中式架构的项目,新功能开发以及Bug维护让人头痛
在这个时候,架构师们会意识到,唯一能解决这个问题的良方是:拆。
一般情况下,我们会尝试把当前的系统拆成多个子系统并部署在不同服务器上,每个子系统尽量承担单一职责,这样既可以解决由于代码累积造成的维护困难,也有助于分散高并发流量带来的压力。
在拆的时候,我们也得知道,各个子系统之间往往存在某种关联性和依赖性,不太可能是孤立的,并且我们通常会把公共业务单独提取出来,希望它能作为独立的应用对外提供服务,即所谓的分布式架构,那么此时要解决的问题是:我们该怎样让分布式系统中各个子系统或子应用之间能够互相通信或调用。
拆分后的架构如图1-2所示。

图1-2 系统拆分后互相调用示意图
实际上,自己实现一个简易的远程通信(或调用)不是难事,比如基于TCP Socket或HTTP的RPC都可以实现,但是在实际项目中,事情远没有这么简单,比如异步处理、容错机制、扩展性、性能问题等都需要做周密的考虑,而Akka就天生拥有异步、分布式消息处理的能力,并且拥有强劲的容错机制和性能,可以帮助开发者解决这类问题。
在产品不断发展的过程中,另外一个不可忽视的挑战是大数据带来的存储和计算问题,存储暂且不表(Akka不直接提供数据存储的方案,当然,在Akka的基础上也可以实现类似的分布式文件存储系统),我们来看看数据的计算问题。
在一个系统中,数据的来源非常广,比如用户交易数据、历史记录、系统日志等,当数据积累到一定程度后(变成Big Data),我们就得考虑挖掘其价值了。
以电商为例,当用户打开浏览器输入域名并按下回车键的那一刻开始,系统就默默地在记录用户数据了,比如访问时间、终端设备类型、用户IP等;当用户看到某个商品并点击链接后,系统会收集并更新商品点击数(当然,也有可能是广告);当用户满怀期望地加入购物车后,系统会把该商品记录到用户的“意向清单”中;当用户毫不犹豫地完成支付时,系统已经生成订单数据并考虑向你推荐其他匹配商品了(笑)。这是笔者虚拟出来的一个数据收集场景,在实际项目中,收集的数据维度只会比这更多,生成的数据量也会更大。很多大型的电商平台(比如亚马逊、淘宝等)都有自己的“个性化推荐系统”,该系统会根据大量的历史数据(比如浏览、购买、交易,评论等)预测(计算)出用户可能的喜好,以此做出合理的商品推荐,进而提升购买转化率。
面对大量的计算任务,系统怎样才能快速实时地得到想要的结果呢?很显然,依靠单核CPU的处理能力已不足以进行如此密集的计算(摩尔定律的失效),一般情况下,我们的解决方案是:把计算拆分成多个子任务实现并行(单机多核或分布式集群)执行。在Java中,我们可以通过Fork/Join等框架来实现单机的并行程序,但是假如想要在单机或分布式以相同的模式去处理计算,很明显这些框架是远远不够的,除此之外,我们还必须考虑多节点计算时的容错、分布式通信等问题。
由此可见,要从头实现这样一个解决方案并非易事,很多时候,我们希望选择一款设计精良,易于使用的框架来处理这些问题,而Akka正是为此而生!
1.1.2 Akka是什么
Akka是一款高性能、高容错性的分布式&并行应用框架,遵循Apache 2开源许可,底层通过JVM上另外一个流行的语言Scala实现,提供Java&Scala API(本书采用Java进行代码演示)。它基于经典的Actor并发模型(即所有的消息都是基于Actor组件进行传递,后面我们会做详细介绍),拥有如下特点:
❑ 并行与并发:提供对并行与并发的高度抽象。
❑ 异步非阻塞:Akka-Actor消息通信都是基于异步非阻塞。
❑ 高容错性:为跨多JVM的分布式模型提供强劲的容错处理,号称永不宕机。
❑ 持久化:Actor携带的状态或消息可以被持久化,以便于在JVM崩溃后能恢复状态。
❑ 轻量级:每个Actor大约只占300bytes,即1G内存可容纳接近300万个Actor。
基本上,Akka从底层就解决了我们大多数分布式&并行程序常见的难题,让工程师更专注于业务实现,同时,它也保留了多个扩展接口及配置,便于满足个性化定制的需要!