Akka框架简介

Akka是JAVA虚拟机平台上构建高并发、分布式和容错应用的工具包和运行。Akka用Scala语言编写,同时提供了Scala和Java的开发接口。Akka处理并发的方法基于Actor模型,Actor之间通信的唯一机制就是消息传递。

Akka特点:

Akka框架简介 - 图1对并发模型进行了更高的抽象

Akka框架简介 - 图2是异步、非阻塞、高性能的事件驱动编程模型

Akka框架简介 - 图3是轻量级事件处理(1GB内存可容纳百万级别个Actor)

Akka框架简介 - 图4它提供了一种称为Actor的并发模型,其粒度比线程更小,你可以在系统中启用大量的Actor。

Akka框架简介 - 图5它提供了一套容错机制,允许在Actor出现异常时进行一些恢复或重置操作。

Akka框架简介 - 图6Akka既可以在单机上构建高并发程序,也可以在网络中构建分布式程序,并提供位置透明的Actor定位服务。

maven依赖:

  1. <dependency>
  2. <groupId>com.typesafe.akka</groupId>
  3. <artifactId>akka-agent_2.12</artifactId>
  4. <version>2.5.13</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.typesafe.akka</groupId>
  8. <artifactId>akka-actor_2.12</artifactId>
  9. <version>2.5.13</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>com.typesafe.akka</groupId>
  13. <artifactId>akka-remote_2.12</artifactId>
  14. <version>2.5.13</version>
  15. </dependency>

Actor模型

在并发程序中线程是并发程序的基本执行单元,但在Akka中执行单元是Actor。传统并发程序是基于面向对象的方法,通过对象的方法调用进行信息传递,如果对象的方法修改对象本身的状态,在多线程下就可能出现对象状态的不一致,此时就必须对方法调用进行同步,而同步操作会牺牲性能。

在Actor模型中并不是通过Actor对象的某个方法来告诉Actor需要做什么,而是给Actor发送一条消息。当一个Actor收到消息后,它有可能根据消息的内容做出某些行为,如更改自身状态,此时这个状态的更改是Actor自身进行的,并非由外界干预进行的。

Akka框架简介 - 图7

Greeter定义

Akka框架简介 - 图8

HelloWorld定义

Akka框架简介 - 图9

sample.conf

Akka框架简介 - 图10

main方法

Akka框架简介 - 图11

运行结果

第一行打印了HelloWorld Actor的路径,它是系统内第一个被创建的Actor。路径为:akka://hello/user/helloworld。第一个hello表示ActorSystem的系统名称,即构造时第一个入参。user表示用户Actor,所有的用户Actor都会挂载在user路径下。最后helloworld是这个Actor的名字。

第二行打印了Greeter Actor的路径,三、四行为Greeter中输出的信息。第五行表示系统遇到了一条消息投递失败,原因是HelloWorld将自身停止了,导致Greeter发送的信息无法成功投递。

当使用Actor进行并发开发时,关注点已经不在线程上了,线程调度已经被Akka框架进行封装,只需关注Actor对象即可。Actor对象之间的通过显示的消息发送来传递信息。

当系统内有多个Actor时,Akka会自动在线程池中选择线程来执行我们的Actor,不同的Actor可能会被同一个线程执行或者一个Actor可能被不同的线程执行。

注意:不要在一个Actor中执行耗时的代码,这样可能会导致其他Actor的调度出现问题。

消息投递

Akka应用是由消息驱动的,消息是除Actor之外最重要的核心组件。在Actor之间传递的消息应该满足不变性,即不变模式,可变的消息无法高效的在并发环境中使用。在Akka中推荐使用不可变对象。在代码中可以使用final字段声明,在消息构造完成后,就不能再发生改变了。

消息投递策略:

Akka框架简介 - 图12至多一次投递:此策略中每一条消息最多会被投递一次,可能会偶尔出现投递失败的情况,从而导致消息丢失。此策略高性能。

Akka框架简介 - 图13至少一次投递:此策略中每一条消息至少会被投递一次,直至成功。在一些偶然的情况,接收者可能会收到重复消息,但消息不会丢失。此策略需要保存消息投递的状态并不断重试。

Akka框架简介 - 图14精确投递:所有消息保证被精确的投递并成功接收一次,既不会丢失也不会重复。此策略成本最高且不易实现。

关于消息的可靠性:没有必要在Akka层保证消息的可靠性,这样做成本太高且无必要。消息可靠性应该在应用的业务层进行保证,有时丢失一些消息是符合应用要求的。

消息投递的顺序性:Akka可以保证在一定程度上的投递顺序性。如Actor A1向A2顺序发送了M1、M2、M3三条消息,Actor A3想A2顺序发送了M4、M5、M6三条消息,则系统可以保证:

Akka框架简介 - 图15如果M1无丢失,它一定先于M2、M3被A2收到。

Akka框架简介 - 图16如果M2无丢失,它一定先于M3被A2收到。

Akka框架简介 - 图17如果M4无丢失,它一定先于M5、M6被A2收到。

Akka框架简介 - 图18如果M5无丢失,它一定先于M6被A2收到。

Akka框架简介 - 图19对于A2来说,来自A1向A3的消息并没有顺序性保证。

Akka框架简介 - 图20

另外这种消息投递规则不具备可传递性,如下图:

Akka框架简介 - 图21

C收到M1和M2的顺序是没有保证的

—参考文献《实战Java高并发程序设计》

一、背景

  1. 大型服务系统由于业务或功能的复杂性,为了维护和升级的便利,往往在架构上按对系统进行拆分,按不同功能拆分成不同的子服务,并进行分布式的部署。但在我们的实践中,对于服务间调用的容错、扩展性、并发性能等问题还需要做严谨的考虑或设计,而由于各种各样的原因工程师们的设计往往有所欠缺。<br /> 对于多线程编程,经常会出现的缺点:线程维护困难、子线程出错后难以恢复、线程阻塞时浪费时间和资源;另外对于密集的计算任务,我们的系统需要达到很高的并发性能,单机系统资源无法满足计算需求,而类似javafork/join框架又很难在分布式环境下简易地对并发计算进行架构设计。<br /> akka框架非常适合解决上述问题。akka框架是一款高性能、高容错性的分布式并发应用框架。akka底层采用scala语言实现,并基于actor并发模型,天然拥有异步、分布式能力,且具有很好的并发性能和容错机制。

二、akka特点

akka典型的特点:

  1. 并发模型:基于actor模型,对并发进行高层次的抽象;
  2. 异步能力:基于actor模型进行通信,天然具有异步非阻塞的特点;
  3. 高容错性:通过父子actor监督机制进行容错处理,为akka分布式模型提供高容错特性;
  4. 轻量级: 每个actor只占300bytes左右的内存,1G内存即可容纳百万级数量的actor;
  5. 位置透明:akka对actor地址进行了抽象、屏蔽了本地地址和远程地址的差异,对开发者透明
  6. 持久化:actor状态或消息可以被持久化,在jvm宕机后actor可以恢复;

三、akka的actor模型

  1. actor模型是对并发模型的高层次抽象,从底层屏蔽了线程、锁机制的管理,为应用开发提供了简单易用的高层次api

Akka框架简介 - 图22

actor模型.png

  1. actor模型的几个特征:
  1. 程序的计算都在actor中进行。actor实例是程序的最小运算单元;
  2. actor之间只能通过消息进行通信。消息是异步传递的,每个actor都有一个邮箱,该邮箱接收其它actor发送的消息,actor实例从邮箱中取出消息进行处理。actor实例内部一次只能同步处理一个消息,因此可以安全的进行状态处理不用进行程序加锁。由于对消息的处理是异步的,所以发送完消息后可以立即返回进行下一步处理(当然也可以等待处理完成)。
  3. actor可以响应其它actor发送的消息,并可以更改本身的状态或行为、发送消息给其它actor、创建子actor、对其它actor进行监督

四、akka架构体系

  1. akka中,整个actor体系被抽象成一个公共的actor系统,即ActorSystemActorSystem是一个层级结构,通过"父监督"模式和DeathWatch模式限定了actor的管理策略。<br /> akka还提供了诸多的配套组件,例如网络服务、持久化等。

ActorSystem

actor组件

akka中actor组件具有几个特征:

  • actor引用(Actor Reference)
    akka不能通过new的方式创建引用。代替new的方式是,通过actorOf(创建actor)或actorSelection(查找actor)等方式返回Actor对象引用。对开发者而言,actor位置透明(可能存在于本地或远程)。
  • 状态(State)
    actor在不同时刻的状态通常用变量来标识。akka在底层为每个actor抽象一个轻量级的执行“线程”,实现了对状态的隔离。
  • 行为(Behavior)
    actor在接受到消息后可以对消息进行处理,或者转发给其它actor处理。
  • 监督策略 (Supervisor Strategy)
    actorSystem是一个层级结构,父actor对子actor具有监管的能力,可以针对子actor的异常进行:恢复、重启、停止、失败上溯等处理方案,另外提供了One-For-One(默认,只对异常的子actor进行处理)和All-For-One(对所有子actor进行处理)两种监督策略。

邮箱

每个actor都拥有自己的邮箱,所有接受的消息会先进入邮箱,actor从邮箱中取出消息进行处理。akka自带多种邮箱类型,并提供RequiresMessageQueue接口供开发者自定义特定类型的邮箱。

路由

actor消息也可以通过路由进行发送,路由可以是一个Router对象,也可以是一个自包含的actor:管理者所有的Routee(路由目标)。开发者可以根据需要选择不同的路由类型,如:轮询、随机、广播等。

网络服务
  1. 提供远程actor和分布式集群的基础能力,包含I/O、网络通信、序列化配置、gossip通信协议、节点管理、集群分片等

http、websocket模块
  1. akka提供了处理 httpwebsocket协议的基础模块,可以在此基础上进行开发。

持久化
  1. akka提供actor的状态持久化方案,在程序出错、宕机等场景下进行恢复。

五、总结

  1. akka具有异步、分布式、高容错等特性,适合作为分布式应用的基础开发框架,比如,目前比较火的流计算引擎flink也采用akka作为分布式通信框架。开发者也可以用akka打造自己分布式应用服务!