Akka学习笔记

持续更新中….
目录

Akka官网

https://doc.akka.io/docs/akka/current/guide

Part 1 Actor结构

Actor的层次结构

这里写图片描述
所有的Actor都有一个父级Actor,system.actorOf()方法在/user目录下创建Actor,contextOf()方法在父级Actor下创建Actor。

Actor的生命周期

这里写图片描述
当一个actor被关闭时,它的所有子节点也将会被递归地关闭。这样可以很好的避免资源的浪费还有资源的泄露,例如当子节点中有一些打开的socket或者文件。事实上,在处理低层次的多线程代码时,一个通常被忽视的困难是各种并发资源的生命周期管理。

为了停止一个参与者,推荐的模式是调用getContext().stop(getSelf())在actor中停止自身,通常作为对某个用户定义的停止消息的响应,或者当参与者完成它的工作时。从技术上讲,通过调用getContext().stop(actorRef)来阻止另一个参与者是可行的,但是阻止任意的行为者被认为是一种不好的做法:尝试给他们发送一个PoisonPill或自定义的停止消息,让收到消息的Actor自己停止。

Akka actor API公开了许多可以在actor实现中覆盖的生命周期hooks。最常用的是preStart()和postStop()。

  • preStart():在Actor开始之后,处理第一条消息之前调用

  • postStop():在Actor停止之后条用,一旦调用,将不会处理任何消息

失败处理

一旦一个actor出错(抛出一个异常或者在receive方法中抛出)它会暂停,子级的错误会抛给父级,然后父级觉得如何处理异常,父级是作为子级的监视者,Akka提供的默认的监视策略是停止子级然后重启它。

Part 2 Actors

Actor模型对于高并发的分布式系统提供了更高层次的抽象。它让开发者可以避免显式的使用锁和管理线程,使得开发一个正确的并发系统更加容易。

创建Actors

定义一个Actor类

import akka.actor.AbstractActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;

public class MyActor extends AbstractActor {
  private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);

  @Override
  public Receive createReceive() {
    return receiveBuilder()
      .match(String.class, s -> {
        log.info("Received String message: {}", s);
      })
      .matchAny(o -> log.info("received unknown message"))
      .build();
  }
}

Props

Props是一个配置类用于创建actor时提供具体的参数

import akka.actor.Props;
Props props1 = Props.create(MyActor.class);
Props props2 = Props.create(ActorWithArgs.class,
  () -> new ActorWithArgs("arg")); // careful, see below
Props props3 = Props.create(ActorWithArgs.class, "arg");

区别???待解决

使用Props创建Actors

通过将Props的实例传给ActorSystem或者ActorContext的工厂方法ActorOf来创建Actors。

import akka.actor.ActorRef;
import akka.actor.ActorSystem;
public class FirstActor extends AbstractActor {
  final ActorRef child = getContext().actorOf(Props.create(MyActor.class), "myChild");

  @Override
  public Receive createReceive() {
    return receiveBuilder()
      .matchAny(x -> getSender().tell(x, getSelf()))
      .build();
  }
}

调用actorOf方法返回的是ActorRef的实例,他是actor实例的引用,是唯一操作Actor的方法。

依赖注入

Inbox

Actor API

ActorSelection

Lifecycle Monitoring aka DeathWatch

为了在另一个Actor终止(即永久停止,而不是临时失败和重新启动)时被通知,Actor可以注册自己,以接收由另一个Actor在终止时发送的终止消息。该服务由actorSystem的DeathWatch组件提供。

import akka.actor.Terminated;
public class WatchActor extends AbstractActor {
  private final ActorRef child = getContext().actorOf(Props.empty(), "target");
  private ActorRef lastSender = system.deadLetters();

  public WatchActor() {
    getContext().watch(child); // <-- this is the only call needed for registration
  }

  @Override
  public Receive createReceive() {
    return receiveBuilder()
      .matchEquals("kill", s -> {
        getContext().stop(child);
        lastSender = getSender();
      })
      .match(Terminated.class, t -> t.actor().equals(child), t -> {
        lastSender.tell("finished", getSelf());
      })
      .build();
  }
}

也可以通过使用context.unwatch(target)来观察另一个Actor的活动轨迹。即使已终止的消息已经在邮箱中被排队,它也能正常工作;在调用unwatch后,将不再处理该actor的终止消息。

Identifying Actors via Actor Selection

消息和不变性(Immutability)

重要:消息可以是任何类型的对象,但是必须是不可变的,虽然Akka框架并没有在代码上强制要求。

发送消息

可以使用下面两个方法去发送消息:
- tell:是“fire-and-forget”模式,既异步的发送消息,然后立即返回
- ask:异步发送消息,然后返回一个代表返回值的Future对象

接收消息

接收超时时间

public class ReceiveTimeoutActor extends AbstractActor {
  public ReceiveTimeoutActor() {
    // To set an initial delay
    getContext().setReceiveTimeout(Duration.create(10, TimeUnit.SECONDS));
  }

  @Override
  public Receive createReceive() {
    return receiveBuilder()
      .matchEquals("Hello", s -> {
        // To set in a response to a message
        getContext().setReceiveTimeout(Duration.create(1, TimeUnit.SECONDS));
      })
      .match(ReceiveTimeout.class, r -> {
        // To turn it off
        getContext().setReceiveTimeout(Duration.Undefined());
      })
      .build();
  }
}

关闭Actor

import akka.actor.ActorRef;
import akka.actor.AbstractActor;

public class MyStoppingActor extends AbstractActor {

  ActorRef child = null;

  // ... creation of child ...

  @Override
  public Receive createReceive() {
    return receiveBuilder()
      .matchEquals("interrupt-child", m ->
        getContext().stop(child)
      )
      .matchEquals("done", m ->
        getContext().stop(getSelf())
      )
      .build();
  }
}

PoisonPill

你也可以发送一个akka.actor.PoisonPill。毒丸消息,当消息被处理时,它将停止Actor。毒丸作为普通消息排队,并将在邮箱中已经排队的消息后处理。

victim.tell(akka.actor.PoisonPill.getInstance(), ActorRef.noSender());

杀死Actor

你也可以发送一个Kill消息,它和毒丸消息不一样会抛出一个异常,这个Actor将会暂停操作,它的监视者将会被调用去处理这个异常,也许是恢复,重启或者完全关闭它。

victim.tell(akka.actor.Kill.getInstance(), ActorRef.noSender());

// expecting the actor to indeed terminate:
expectTerminated(Duration.create(3, TimeUnit.SECONDS), victim);

优雅的关闭

如果你需要等待终止或组合多个参与者的命令终止,那么gracefulStop方法是非常有用的。

try {
  CompletionStage<Boolean> stopped =
    gracefulStop(actorRef, Duration.create(5, TimeUnit.SECONDS), Manager.SHUTDOWN);
  stopped.toCompletableFuture().get(6, TimeUnit.SECONDS);
  // the actor has been stopped
} catch (AskTimeoutException e) {
  // the actor wasn't stopped within 5 seconds
}

Become/Unbecome

Stash

Part3 Dispatchers

Part4 Mailboxes

一个Akka的邮箱保存着相应Actor的消息,通常来说,每个Actor都有自己的邮箱,但是一个BalancingPool所有的路由都共享一个邮箱实例。

Mailbox Selection

Part5 Routes

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
内容简介 本书将尝试帮助入门级、中级以及高级读者理解基本的分布式计算概念,并且展示 如何使用 Akka 来构建具备高容错性、可以横向扩展的分布式网络应用程序。Akka 是一 个强大的工具集,提供了很多选项,可以对在本地机器上处理或网络远程机器上处理的 某项工作进行抽象封装,使之对开发者不可见。本书将介绍各种概念,帮助读者理解 网络上各系统进行交互的困难之处,并介绍如何使用 Akka 提供的解决方案来解决这些 问题。 作者简介 Jason Goodwin 是一个基本上通过自学成才的开发者。他颇具企业家精神,在学校 学习商学。不过他从 15 岁起就开始学习编程,并且一直对技术保持着浓厚的兴趣。这对 他的职业生涯产生了重要的影响,从商学转向了软件开发。现在他主要从事大规模分布 式系统的开发。在业余时间,他喜欢自己原创电子音乐。 他在 mDialog 公司第一次接触到 Akka 项目。mDialog 是一家使用 Scala/Akka 的公司, 为主流出版商提供视频广告插入软件。这家公司最终被 Google 收购。他同时还是一名很 有影响力的“技术控”,将 Akka 引入加拿大一家主要的电信公司,帮助该公司为客户提 供容错性更高、响应更及时的软件。除此之 外,他还为该公司中的一些团队教授 Akka、 函数式以及并发编程等知识。 目录 第 1 章 初识 Actor:Akka 工具集以及 Actor 模型的介绍。 第 2 章 Actor 与并发:响应式编程。Actor 与 Future 的使用。 第 3 章 传递消息:消息传递模式。 第 4 章 Actor 的生命周期—处理状态与错误:Actor 生命周期、监督机制、Stash/ Unstash、Become/Unbecome 以及有限自动机。 第 5 章 纵向扩展:并发编程、Router Group/Pool、Dispatcher、阻塞 I/O 的处理以 及 API。 第 6 章 横向扩展—集群化:集群、CAP 理论以及 Akka Cluster。 第 7 章 处理邮箱问题:加大邮箱负载、不同邮箱的选择、熔断机制。 第 8 章 测试与设计:行为说明、领域驱动设计以及 Akka Testkit。 第 9 章 尾声:其他 Akka 特性。下一步需要学习的知识。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值