第七章 使用Akka构建高并发程序

来源:互联网 发布:淘宝手办现货可信? 编辑:程序博客网 时间:2024/06/05 08:26

  • 第七章 使用Akka构建高并发程序
    • 1 新并发模型Actor
    • 2 Akka之 Hello Word
    • 3 有关消息投递的一些说明
    • 4 Actor的生命周期
    • 5 监督策略
    • 6 选择Actor
    • 7 消息收件箱Inbox
    • 8 消息路由
    • 9 Actor的内置状态转换
    • 10 询问模式Actor中的Future
    • 11 多个Actor同时修改数据Agent
    • 12 像数据库一样操作内存数据软件事务内存STM
    • 13 一个有趣的例子并发粒子群的实现
      • 131 什么是粒子群算法
      • 132 粒子群算法的计算过程
      • 133 粒子群算法能做什么
      • 134 使用Akka实现粒子群

第七章 使用Akka构建高并发程序

  • 提供了一种称为Actor的并发模型,其粒度比线程更小,因此可以在系统中大量使用Actor。不仅适用于单机,也适用于分布式程序。

7.1 新并发模型:Actor

  • 在Actor模型中,失去了对象的方法调用,并不是通过调用Actor对象的一个方法告诉Actor需要做什么,而是给Actor发送一条消息。当Actor收到一条消息后,它可能会根据消息的内容做出某些行为,包括更改自身状态。但其状态修改是Actor自己进行的,而非外部调用的。

7.2 Akka之 Hello Word

  • 在Akka中,UntypedActor就是所说的Actor。之所以强调无类型,是因为Akka中,还支持一种有类型的Actor,其可以使用系统其他类型构造,可以缓解java单继承的问题。
  • 使用Actor进行并行程序开发时,关注点已经不在线程上,只需关注Actor对象即可,而Actor对象之间的交流和普通对象的函数调用有着明显的区别,它们是通过显示的消息发送来传递消息的。
  • 当系统中有多个Actor存在时,Akka会自动在线程池中选择线程来执行actor,因此多个不同的Actor可能会被同一个线程执行,一个Actor可能被不同的线程执行。

7.3 有关消息投递的一些说明

  • 整个Akka应用是消息驱动的。消息是Actor之外的重要核心组件,在Actor之间传递的消息应该满足不变性。因此,Akka中的消息推荐使用不可变对象,即final修饰的。
  • 消息投递的三种策略:
    1. 至多一次投递。每一条消息最多会被投递一次,可能会导致消息投递失败,消息丢失
    2. 至少一次投递。每一条消息至少会被投递一次,直到成功为止。不会发生消息丢失,但是可能会发生消息重复
    3. 精确的消息投递。保证所有消息都会被成功投递一次,既不会有丢失也不会重复。
  • 实际上,没必要在Akka层保证消息的可靠性,成本太高,也没有必要。消息的可靠性可以在应用层确保。
  • 顺序性:在一定程度上保持消息的顺序性。如A1向A2顺序发送了M1、M2和M3,三条消息,A3向A2顺序发送了M4、M5和M6三条信息
    1. 如果M1没有丢失,那它一定先于M2和M3被A2收到
    2. 如果M2没有丢失,那它一定先于M3被A2收到
    3. 如果M4没有丢失,那它一定先于M5和M6被A2收到
    4. 如果M5没有丢失,那它一定先于M6被A2收到
    5. 对A2来说,来自A1和A3的消息可能交织在一起,没有顺序保证。消息的传递不具有传递性。如A向C发送了M1,接着,A向B发送了M2,B将M2转给了C,那么C收到M1和M2没有先后顺序保证

7.4 Actor的生命周期

  • 一个Actor在actorOf函数被调用后开始建立,Actor实例创建后,会回调preStart方法。如果actor在工作过程中出现异常,需要重启,会回调preRestart方法(老的实例上),接着系统会创建一个新的actor实例,虽然是新的,但表示同一个actor,当新实例创建后,postRestart方法会被调用,表示启动完成。stop方法可以停止actor,其停止时,postStop会被调用,同时这个actor的监视者会收到Terminated消息。

7.5 监督策略

  • 两种:
    • OneForOneStrategy(默认策略)
    • 父Actor只会对出问题的子Actor进行处理。
    • AllForOneStrategy
    • 父Actor会对所有的子都进行处理

7.6 选择Actor

  • ActorSelection类可以根据path匹配规则,批量获取actor

7.7 消息收件箱(Inbox)

  • 可以方便地对Actor进行消息发送和接收,大大方便了应用程序与Actor之间的交互。

7.8 消息路由

  • 路由器组件,实现消息调度的封装。提供几种消息路由策略如,轮询选择actor进行消息发送,随机消息发送,将消息发送给最为空闲的actor,组内消息广播。

7.9 Actor的内置状态转换

  • 一个actor内部消息处理函数可以拥有多个不同的状态,在特定的状态下,可以对同一条消息进行不同的处理,状态之间也可以任意切换。

7.10 询问模式:Actor中的Future

7.11 多个Actor同时修改数据:Agent

  • 提供了对一个变量的异步更新。

7.12 像数据库一样操作内存数据:软件事务内存(STM)

  • 具有隔离型、原子性和一致性。但不具有持久性。确保多个actor协作完成一项任务的问题。

7.13 一个有趣的例子:并发粒子群的实现

  • 粒子群算法(PSO)是一种进化算法。与遗传算法非常类似,可以用来解决一些优化问题。可以将一些NP问题转变为一个多项式问题。但是有代价的,进化算法不保证可以从结果中得到最优解。

7.13.1 什么是粒子群算法

  • 一种基于迭代的优化算法。广泛应用于函数优化与神经网络训练等方面。源于鸟类的觅食的群体表现。

7.13.2 粒子群算法的计算过程

  1. 初始化所有粒子,粒子的位置随机生成。计算每个粒子当前的适应度,并将此设为当前粒子的个体最优值(记为pBest)
  2. 所有粒子将自己的个体最优值发送给管理者Master。Master获得所有粒子的信息后,筛选出全局最优的解(记为gBest)
  3. Master将gBest通知所有粒子,所有粒子便知道全局最优点的位置
  4. 接着,所有粒子根据自己的pBest和全局gBest,更新自己的速度,在有了速度后,再更新自己的位置
  5. 如果粒子产生了新的个体最优点,则发送给Master,在此,转到步骤2

7.13.3 粒子群算法能做什么

  • 最优化计算。

7.13.4 使用Akka实现粒子群

  • 由于粒子数量过大,因此一般的线程模型无法满足,但Actor本身作为轻量级的并发单元,一个线程可以对应多个actor,因此适合进行这种并发计算。