1.概述

转载:Akka传递消息

1.1 消息传递

Akka 有 4 种核心的 Actor 消息模式: tell 、ask 、forward 和 pipe。

  • Ask:向 Actor 发送一条消息,返回一个 Future。当 Actor 返回响应时,会返回 Future。不会向消息发送者的邮箱返回任何消息。

  • Tell:向 Actor 发送一条消息。所有发送至 sender()的响应都会返回给发送消息的 Actor。

  • Forward:将接收到的消息再发送给另一个 Actor。所有发送至 sender() 的响应都会返回给原始消息的发送者。

  • Pipe:用于将 Future 的结果返回给 sender() 或 另外一个 Actor。如果正在使用 Ask 或是处理一个 Future,那么使用 Pipe 可以正确地返回 Future 的结果。

1.2 消息不可变

可变消息可能偶尔会在某个时刻给程序造成一些无法描述的坏情况因此要保证消息最好是不可变的,不仅要保证引用不可变,也要保证类型不可变。使用 final 关键字可以保证引用不可变,使用 String 替代 StringBuffer 可以保证类型不可变。因为 String 是不可变的,但是 StringBuffer 的内容是追加的。


无论什么时候,只要需要在线程之间共享数据,就应该首先考虑将消息定义成不可变的。

1.3 Ask 消息模式

Ask 模式会生成一个 Future,表示 Actor 返回的响应。Actor 系统外部的普通对象与 Actor 通信时经常会使用这种方式。在调用 Ask 向 Actor 发起请求时,Akka 实际上会在发起方的 Actor 系统中创建一个临时的 Actor。接收请求的 Actor 在返回响应时使用的 sender()引用就是这个临时的 Actor。当一个 Actor 接收到 ask 请求发来的消息并返回响应时,这个临时 Actor 会使用返回的响应来完成 Future。


因为 sender()引用就指向临时 Actor 的路径,所以 Akka 知道用哪个消息来完成 Future。 Ask 模式要求定义一个超时参数,如果对面没有在超时参数限定的时间内返回这个响应,那么 Future 就会返回失败。

因为 sender()引用就指向临时 Actor 的路径,所以 Akka 知道用哪个消息来完成 Future。 Ask 模式要求定义一个超时参数,如果对面没有在超时参数限定的时间内返回这个响应,那么 Future 就会返回失败。

Ask 模式看上去很简单, 不过它是有隐藏的额外性能开销的。 首先, ask 会导致 Akka 在/temp 路径下新建一个临时 Actor。 这个临时 Actor 会等待从接收 ask 消息的 Actor 返回的响应。 其次, Future 也有额外的性能开销。 Ask 会创建 Future, 由临时 Actor 负责完成。

这个开销并不大,但是如果需要非常高频地执行 ask 操作,那么还是要将这一开销考虑在内的。Ask 很简单,不过考虑到性能,使用 tell 是更高效的解决方案。

1.4 Tell 消息模式

Tell 是最简单的一种消息模式Tell 通常被看做是一种 fire-and-forget 消息传递机制,无需指定发送者;不过通过一些巧妙的方法,也可以使用 tell 来完成request/reply风格的消息传递

Tell 是 ActorRef/ActorSelection 类的一个方法。它可以接收一个响应地址作为参数,接收消息的 Actor 中的 sender()就是这个响应地址。在 Scala 中,默认情况下,sender 会被隐式定义为发送消息的 Actor。如果没有 sender(如在 Actor 系统外部发送请求),那么响应地址不会默认设置为任何邮箱(叫做 DeadLetters)。

在 Java 中并没有隐式定义或是默认参数,所以必须提供 sender。如果不想指定任何特定的 sender 作为响应地址,那么应该遵循如下写法:

  • 从一个 Actor 内部发送消息,使用 self()。 如:actor.tell(message,self())

  • 从 Actor 系统外部发起消息,使用 noSender()。如:actor.tell(message,ActorRef.noSender())

相较于ASK,使用 Tell 处理响应

我们可以在 Actor 中将一些上下文信息存储在一个 map 中,将 map 的 key 放在消息中一起发送。然后,当有着相同 key 的消息返回时, 就可以恢复上下文, 完成消息的处理了。 这就允许我们能够使用类似 ask 模式的语义,又可以避免 ask 造成的额外性能开销。


乍一看这种做法的性能开销似乎比使用 ask 时还要大,但是如果要把许多个 Actor 组合起来,这种做法就省去了使用 ask 时的超时以及创建额外 Actor 的问题。这样我们就能够控制超时发生的位置。

由于 tell 不需要提供超时参数,所以我们通常都会想要在某些时候及时生成超时信息。

1.5 Forward 消息模式

Tell 在语义上是用于将一条消息发送到另一个 Actor ,并将响应地址设置为当前 Actor。而Forward不是,初始发送者保持不变,只不过新增了一个收件人。使用 Forward 传递消息时,响应地址就是原始消息的发送者。

1.6 Pipe

有时候需要将 Actor 中的某个 Future 返回给请求发送者。sender()是一个方法,所以要在 Future 的回调函数中访问 sender(),我们必须存储一个指向 sender() 的引用:

final ActorRef senderRef = sender();future.map(x -> {senderRef.tell(x,ActorRef.noSender())});

Future 的回调函数(比如上面的 map)会在另一个线程中执行,所以未必能够通过 sender()访问到正确的值。这就是需要将 sender()存储起来的原因。但是这个原因并不清晰。比如我最开始疑惑为什么不直接将 sender()写到 map 函数中,而使用上面存储起来的引用。

而通过使用 Pipe 模式,就可以避免上面的疑惑。Pipe 会得到一个 Future 结果,然后将 Future 的结果返回给 sender()。

pipe(future,system.dispatcher()).to(sender());

pipe 接收 Future 的结果作为参数,然后将其传递给所提供的 Actor 引用。因为这里的 sender() 执行在当前线程上,所以可以直接调用 sender()。不用像之前那样存储 sender()的引用。

【Akka】Akka 传递消息相关推荐

  1. “不传递消息、不使用邻接矩阵、在边集上训练”: 从对比链接中蒸馏自知识:非消息传递的图节点分类...

    来源:深度学习与图网络本文约800字,建议阅读5分钟 本文从图网络的边中蒸馏知识,使 MLP 在图节点分类任务上达到了 GNN 的表现. 这篇文章从图网络的边中蒸馏知识,使 MLP 在图节点分类任务上 ...

  2. Android开发--Service和Activity通过广播传递消息

    Android的Service也运行在主线程,但是在服务里面是没法直接调用更改UI,如果需要服务传递消息给Activity,通过广播是其中的一种方法: 一.在服务里面发送广播 通过intent传送数据 ...

  3. Flume案例:模拟两个agent之间传递消息的场景

    模拟两个agent之间传递消息的场景 说明: 1.在hadoop1机器上有一个flume agent,通过exec监听tail命令输出的结果. 2.新增的结果通过avro sink的方式下层到hado ...

  4. 通过小程序给公众号传递消息_多输入现场消息传递应用程序概念

    通过小程序给公众号传递消息 by Dawid Woldu 戴维德·沃尔杜(Dawid Woldu) 多输入现场消息传递应用程序概念 (A multi-input field messaging app ...

  5. MFC小笔记:父子窗口传递消息

    一.需求 MFC程序可能有许多个对话框,有主对话框,有子对话框,本文介绍父子对话框之间的消息传递.适用于外部事件.外部通知等事件.为简单起见,只针对父窗口传递消息到子窗口. 二.界面 主界面为对话框, ...

  6. Android学习笔记(十二)——Fragment向Activity传递消息

    点击Fragment中"给Activity传递消息"按钮,使Activity中TextView中原本的text="hello"换成"你好" ...

  7. MFC用PostMessage传递消息

    1.自定义消息ID. #define WM_MY_MESSAGE (WM_USER+100)         WM_USER为windows系统为非系统消息保留的ID,这里至少要用100,因为其它控件 ...

  8. C#窗口间传递消息(聊天记录)

    C#窗口间传递消息 链接:http://blog.csdn.net/chenyuling/archive/2007/05/25/1625907.aspx 链接:http://www.cnblogs.c ...

  9. wxpython多线程 假死_wxpython多线程防假死与线程间传递消息实例详解

    wxpython中启用线程的方法,将GUI和功能的执行分开. 网上关于python多线程防假死与线程传递消息是几年前的,这里由于wxpython和threading模块已经更新最新,因此给出最新修改代 ...

最新文章

  1. python模块之json,pickle
  2. 【JVM】类加载器:双亲委派机制、沙箱安全机制
  3. 『原创』+『参考』基于PPC的图像对比程序——使用直方图度量
  4. hide handkerchief(hdu2104)
  5. Apache Kafka-通过设置Consumer Group实现广播模式
  6. 统一代码风格工具 editorConfig
  7. 银行工作人员违规发放贷款要坐牢吗?
  8. 验证软件需求正确性的四个角度
  9. linux命令cp -a,linux命令_ls命令与cp命令详解(一)
  10. QTP模拟鼠标和键盘事件整理
  11. mysql 日期 明天_mysql 获取昨天日期、今天日期、明天日期以及前一个小时和后一个小时的时间...
  12. WPF 登录界面跳转代码
  13. idea中的maven使用
  14. Python程序设计实验报告【合集】
  15. 看看最新BTA大厂的Java程序员的招聘技术标准,成功入职字节跳动
  16. 云更新网吧系统服务器,云更新2021最新版安装视频教程/网吧无盘系统/万能包PNP驱动...
  17. 一生要看的50部经典电影
  18. flink 简单上手
  19. 数理统计与数据分析第三版习题 第3章 第5题
  20. Python实现经纬度转换

热门文章

  1. CarSim仿真快速入门(三)
  2. contentEditable,window.getSelection详解---可编辑div,容器,设置/获取光标位置,光标处插入内容及光标的操作
  3. SDN之NOS概述——云原生
  4. 水安ABC考试多选练习题库(7)
  5. CS 425 – Database Organization - project 1:HomeImprovement_shop_project
  6. 必备的 Linux 性能诊断分析工具!(文末送书)
  7. system76_这就是System76打开硬件的方式
  8. HR 开发技术(abap 转载)
  9. 二手房买卖中“跳单”行为之探讨
  10. Java虚拟机学习与总结(一)