单机系统,我们使用JAVA API中的Executor、Fork/Join(分而治之)等,就能很好的解决的多线程并发问题,但在分布式集群项目中,它们或许并没有那么完美。
背景
当今社会,人们在享受互联网带来便利的同时,对产品的要求越来越高,响应快、稳定性好。为了达到用户的要求,产品开发或维护阶段,服务化、分布式、并行计算成为开发人员面临的难题。
产品研发期间,用户量小、业务单一,架构师为了产品能够快速迭代,大多采用集中式架构进行开发,项目也能保证质量。但是随着业务的增长,用户逐渐增多,功能不断扩展,这时集中式架构带来的许多问题接踵而至。遇到这种问题,最好的办法或许是系统重构,但考虑到成本太高,时间紧迫,大家基本上都会选择系统拆分。
关于系统拆分,我们通常会按照业务逻辑进行拆分,相同的业务拆分成单独的子系统,尽量保证单一原则,以此来解决代码维护和高并发的问题。
系统拆分之后,我们就需要考虑到各个子系统通信的问题了,通常情况下,我们都是使用基于HTTP的RPC实现通信。但在复杂的项目中,面临异步任务、容错、分布式消息处理、并行计算等问题,就显得有点不足。这时,如果有一个使用简单并能够解决上述问题的框架,就会得到大家的拥抱,Akka因此而生。
上述说了这么多废话,大家看着也累,现在我们就直奔主题,初识Akka。
Akka简介
Akka是在java虚拟机JVM平台上,使用Scala语言编写的一款高性能、高容错性的分布式和并行应用框架。Akka提供了基于JAVA和Scala两种API,大家可以很方便的使用。既然Akka就是为解决上述问题所生,那么它有哪些特点呢?
特点 | 描述 |
并行与并发 | 提供对并行与并发的高度概括 |
异步非阻塞 | 采用消息传递(异步非阻塞)进行通信 |
高容错性 | 为跨多JVM的分布式模型提供强劲的容错处理,号称永不宕机 |
持久化 | 消息以及状态可以被持久化,便于在JVM崩溃后进行恢复 |
轻量级 | 核心Actor大约只占300bytes,节约内存 |
Akka处理并发问题,核心是Actor并发模型,Actor之间采用消息传递进行通信,是Akka最基本的执行单元。那么什么是Actor并发模型呢?
Actor并发模型
Actor模型,最小执行单元就是Actor实例。每一个实例都有自己的状态和行为,系统可以存在成千上万个Actor实例,它们通过消息传递进行通信。每个Actor能发送消息,也能接受消息。当我们要执行某个任务的时候,并不是调用某个Actor实例的接口或者是方法,而是通过发送消息。Actor的消息传递是异步的,也就是说,当一个任务被通知的时候,不用等到执行任务的Actor完成所有过程,就可以继续执行下一步,这种异步通信大大提高了程序的响应速度以及性能。另外,Actor从底层屏蔽掉了线程和锁机制的管理,让开发者可以更加的关注业务,提高开发效率。
在Akka中,每个Actor都有自己的监管对象,也就是它的创建者,它们会负责子Actor的失败处理。另外,某些Actor也需要对生命周期进行监控,以便在不同时期做出正确的响应。监督和监控者也是一个Actor。Actor的创建不能通过"new"的方式,而是需要使用actorOf()或者actor-Selection的方式返回一个ActorRef对象,该对象可能存在本地,也可能存在远程。
在一个项目中,所有的Actor共同组成了Actor系统,即ActorSystem结构。该结构是有层级的,我们必须按照该层次结构进行Actor管理。通常来讲,我们创建的Actor都应该有一个父级Actor,当然最顶层的Actor除外,它负责对子Actor的异常情况进行处理,例如:恢复子级、重启子级、停止子级、扩大化失败。关于这些异常的处理,后续我们会详细讲解。
在Actor系统中,到底是怎样的一个层级关系呢?画一张图简单描述一下:
从中我们可以看出Actor系统中,存在三类顶级的Actor,也就是Root、user、system。系统默认就会启动这三个顶级的Actor,我们创建的Actor只属于其中的一个分支—user。root是最顶层的Actor,所有的Actor都属于它,user、system是它的一个子分支,当我们使用ActorSystem.actorOf()创建Actor时,都属于user分支下,也是我们创建的最高级别Actor,通过ActorContext.actorOf()创建的Actor都是其子级。
关于Actor并发模型,我们就先描述到这里,后续我们会更加完善的讲Actor的特点以及用法。
Akka组件
Akka除了核心使用Actor并发模型之外,还提供了许多其它丰富的组件,例如:邮箱、路由、持久化、网络(远程、集群)等,对分布式和并发进行了高度、统一的抽象,使我们能够轻松的实现一个完整的分布式应用。
关于这几个组件,做一个简单的汇总:
组件 | 描述 |
邮箱 | 每个Actor都有自己的邮箱,其它Actor发送过来的消息都会进入该邮箱。Akka自带多种邮箱类型,也提供自定义邮箱接口 |
路由 | 消息可以通过Actor发送,也可以通过路由发送。可以选择不同的路由策略,比如轮询、广播等,路由也是一个Actor |
状态持久化 | Akka提供了Actor状态的持久化,便于我们在必要时恢复数据 |
网络(远程和分布式集群) | 实现远程Actor和分布式集群的基础,包含I/O、TCP/UDP、序列号配置、节点管理、集群分片等 |
HTTP模块 | 支持HTTP服务端和客户端开发,快速构建高性能的Rest Web服务 |
应用场景
Akka提供这些组件,使得在rest web 、websocket服务、分布式消息处理、日志异步处理、密集数据计算等方向具有很强的能力。对大部分研发团队来说,从零搭建一个高并发的分布式架构,或许会面临诸多挑战,选择Akka,可以帮助你快速搭建。
看到这里,相信大家对Akka有了一个大致的了解,关于如何使用Akka,Actor是如何工作的,下一节,我们再来详谈。
以上内容是我在阅读<<Akka实战>>时,关于Akka的基本内容做的一个总结,如果有不对的地方,望大家批评指正,谢谢。