AKKA官方文档阅读笔记(1)JAVA版2.5.16

准备工作:

以下内容来自文档:https://doc.akka.io/docs/akka/2.5/guide/tutorial_1.html

Actor层级结构

在这里插入图片描述
其实在你用代码创建Actor之前,Akka自己就已经创建三个actor了,它们都是负责监管自己下面的actor的:

  • / 这个就是传说中的跟监管者,是所有actor的祖先,当系统终止时,它一定是最后一个被停止的
  • /user 这个是所有咱们用代码创建的Actor的祖先
  • /system 不晓得这是做啥的,非用户创建的actor的祖先吧
    想搞清楚actor的层级结构,最好就是自己创建一些actor,并打印出它们的引用,你可以在包com.lightbend.akka.sample中增加下面这个类:
package com.lightbend.akka.sample;

import akka.actor.AbstractActor;
import akka.actor.AbstractActor.Receive;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;

class PrintMyActorRefActor extends AbstractActor {
  @Override
  public Receive createReceive() {
    return receiveBuilder()
        .matchEquals("printit", p -> {
          ActorRef secondRef = getContext().actorOf(Props.empty(), "second-actor");
          System.out.println("Second: " + secondRef);
        })
        .build();
  }
}
public class ActorHierarchyExperiments {
  public static void main(String[] args) throws java.io.IOException {
    ActorSystem system = ActorSystem.create("testSystem");

    ActorRef firstRef = system.actorOf(Props.create(PrintMyActorRefActor.class), "first-actor");
    System.out.println("First: " + firstRef);
    firstRef.tell("printit", ActorRef.noSender());

    System.out.println(">>> Press ENTER to exit <<<");
    try {
      System.in.read();
    } finally {
      system.terminate();
    }
  }
}

执行main方法可以看到输出的内容是:

First: Actor[akka://testSystem/user/first-actor#1053618476]
Second: Actor[akka://testSystem/user/first-actor/second-actor#-1544706041]

其中testSystem是ActorSystem的名称,其后的user表示这是用户(就是咱们用代码)创建的Actor,后面就是类似linux文件夹一样的表示方式了,很容易理解。#后面的一串儿数值是Actor的唯一标识,大部分时候不用管

Actor的生命周期

actor的生命是从我们创建它开始,当一个Actor停止时,会先递归地停止它的孩子Actor,这种做法简化了资源释放并避免资源泄露。
推荐在actor内部通过getContext().stop(getSelf())写法来中止它自己,一般是在actor完成它地任务之后收到一个约定好的停止消息,作为对这个消息地响应,停止它自己。也可以通过getContext().stop(actorRef)停止其他地actor,但是这种做法不推荐使用,最好改为给相应的actor发送停止消息
Akka的actor API有很多生命周期相关的钩子你可以去重写,最常用的就是preStart()preStop()了,看名字也很容易理解,preStart()方法一定会在开始处理消息之前被执行。

Actor错误处理

在父Actor和子Actor的整个生命周期中,它们都是紧密相关的,任何时候一个Actor出错了(就是receive方法中抛出了错误),它就会被临时挂起,然后这个错误会传到父级那里(具体怎么传这里没说,其实也是Actor类里的一个方法),父级Actor会决定怎么处理子Actor抛出的这个错误,可以看出,每个Actor负责监管它的子级,默认的监管策略停止并重启子Actor

以下内容来自文档:https://doc.akka.io/docs/akka/2.5/guide/tutorial_3.html

给远程Actor发送消息

发消息给远程actor和本地的actor是类似的,但是我们要记住:

  • 两者的延迟会有较为明显的差别,因为你要考虑带宽和消息的大小
  • 发送远程消息包含更多的步骤也更容易出错,要考虑可靠性
  • 发送本地消息不会对消息做限制,反之,远程消息会限制message size

对于消息发送,Akka有以下两个特性:

  • 消息交付:最多发送一次(消息不会重复发送,但不保证交付)
  • 消息顺序:对于一对发送者和接收者,消息是有序的

消息交付
消息传递的分类往往是以下三类:

  • 最多一次 At-most-once delivery: 每条消息发送接收方会收到0次或者1次。就是有可能收不到但绝不会重复。
  • 至少一次 At-least-once delivery: 每条消息会被潜在地多次发送,至少有一条发送成功。有可能收到重复消息但绝不会丢消息。
  • 准确一次 Exactly-once delivery:每条消息不多不少发送一次

第一种就是Akka采用地,它是性能最高的,开销最小,因为消息即发即弃( fire-and-forget),发送端接收端都不用维护消息的状态。相应的第二种,发送端要维护消息的状态,接收端要有确认机制。第三种是最昂贵的,发送端和接收端都要维护消息状态。

在一个actor系统中, 我们要确定交付的含义 — 在哪一个时间点,系统认为消息发送完成了:

    1. 当消息发送到网络中?
    1. 当消息被目标Actor所在的主机接收时?
    1. 当消息投放到目标Actor所在的邮箱?
    1. 当目标Actor开始处理这条消息?
    1. 当目标Actor处理消息完成?

大部分框架和协议宣称在类似4或5的时候,听起来挺合理的,但是这些框架和协议提供的保证真的能达到4或5的级别吗?举个简单又实际的例子: 用户提交一个订单,我们希望返回此订单被处理并成功写入数据库磁盘中了。

如果我们依赖于成功处理消息,则只要订单已提交给相应API,处理它并将其放入数据库,actor就会报告成功。 不幸的是,在调用API之后,可能会发生以下任何一种情况:

  • 主机崩了
  • 反序列化失败了
  • 数据校验失败了
  • 数据库崩了
  • 代码出BUG了

这表明交付保证不会转化为域级保证。 我们只想在订单实际完全处理和保留后报告成功。 可以报​​告成功的唯一实体是应用程序本身(也就是消费者实际处理消息的代码),因为只有它知道怎样才算处理成功。 没有通用框架可以确定特定域的细节以及在该域中被认为是成功的。

在这个特定的例子中,我们只希望在成功的数据库写入后发出成功信号,数据库确认订单现在已安全存储。 由于这些原因,Akka将保证的责任提升到应用程序本身,即您必须自己实现它们。 这使您可以完全控制要提供的保证。 现在,让我们考虑Akka提供的消息排序,以便于推理应用程序逻辑。

消息排序
在Akka中,对于给定的一对Actor(发送者和接收者),直接从第一个发送到第二个的消息不会乱序接收。 强调:这种保证仅适用于消息直接发送,而不是使用中间者(中介)
如果:

  • Actor A1 给A2发送了消息: M1, M2, M3
  • Actor A3 也给A2发送了消息: M4, M5, M6

这意味着:
M1一定比M2, M3先到
M2一定比M3先到
M4一定比M5, M6先到
M5一定比M6先到
A2从A1和A3处收到的消息可能会是夹杂着间隔着的
因为是不可靠交付,任何消息都有可能丢失, 也就是到达不了A2

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值