Akka入门

Akka是一个异步非阻塞的高并发处理框架,基于Actor模型,提供分布式集群管理和流处理等功能。Actor通过消息传递改变状态,不占用调用方CPU时间,且Akka的Actor是无状态的。文章介绍了Akka的Actor模型概念,以及如何在Java中创建和使用Actor,包括tell和ask两种消息交互方式。
摘要由CSDN通过智能技术生成

一、什么是Akka?

 Akka是一个异步非阻塞高并发处理框架,它是一系列框架,包括akka-actor, akka-remote, akka-cluster, akka-stream等,分别具有高并发处理模型——actor模型,远程通信,集群管理,流处理等功能。Akka具有一下特点:

  • Akka屏蔽了Java的多线程和锁,转而使用Actor模型,一般的工程师可以在不了解如何优化Java多线程编程的情况下,也能实现非常高性能的系统
  • Actor设计之初就天然满足了分布式,而且粒度较小,单机上可以跑上百万的Actor
  • Akka屏蔽了分布式集群中底层的通讯机制,对于开发者来说,只要根据业务写好Actor即可
  • Akka直接提供了分布式下高可用、弹性、动态扩容的功能,无需再次开发。

二、Actor模型​​​​​​​

由于AKka的核心是Actor,而Actor是按照Actor模型进行实现的,所以在使用Akka之前,有必要弄清楚什么是Actor模型
Actor模型最早是1973年Carl Hewitt、Peter Bishop和Richard Seiger的论文中出现的,受物理学中的广义相对论(general relativity)和量子力学(quantum mechanics)所启发,为解决并发计算的一个数学模型。

Actor模型所推崇的哲学是”一切皆是Actor“,这与面向对象编程的”一切皆是对象“类似。但不同的是,在模型中,Actor是一个运算实体,它遵循以下规则:

  • 接受外部消息,不占用调用方(消息发送者)的CPU时间片
  • 通过消息改变自身的状态
  • 创建有限数量的新Actor
  • 发送有限数量的消息给其他Actor

很多语言都实现了Actor模型,而其中最出名的实现要属Erlang的。Akka的实现借鉴了不少Erlang的经验。

三、Actor模型​​​​​​​的实现

​​​​​​​AkkaActor接受外部消息是靠Mailbox,参见下图

对于Akka,它又做了一些约束:

  • 消息是不可变的
  • Actor本身是无状态的

基本的Actor例子

引入依赖

<dependency>
            <groupId>com.typesafe.akka</groupId>
            <artifactId>akka-actor_2.11</artifactId>
            <version>2.4.7</version>
        </dependency>

编写Actor

public class ActorDemo extends UntypedActor {
    private LoggingAdapter log = Logging.getLogger(this.getContext().system(), this);

    @Override
    public void onReceive(Object message) throws Exception, Exception {
        if (message instanceof String) {
            log.info(message.toString());
            System.out.println(getSelf() + "---->" + message + " " + Thread.currentThread().getName());
        } else {
            unhandled(message);
        }
    }

    public static void main(String[] args) {
        ActorSystem system = ActorSystem.create("sys");
        ActorRef actorRef = system.actorOf(Props.create(ActorDemo.class), "actorDemo");
        actorRef.tell("Hello Akka", ActorRef.noSender());
    }
}

注意:
ActorSystem是一个较重的存在,一般一个应用里,只需要一个ActorSystem
在同一个ActorySystem中,Actor不能重名。

Actor的Path

Akka中的Actor不能直接被new出来,而是按一棵树来管理的,每个Actor都有一个树上的path

实际上,在我们创建自己的Actor之前,Akka已经在系统中创建了三个名字中带有guardianActor

  • / 最顶层的 root guardian。它是系统中所有Actor的父,系统停止时,它是最后一个停止的
  • /user guardian。这是用户自行创建的所有Actor的父。这里的user跟用户没有一毛钱关系
  • /system 系统guardian

在上面的例子里,我们使用的是system.actorOf来创建ActoractorOf返回的并不是Actor自身,而是一个ActorRef,它屏蔽了Actor的具体物理地址(可能是本jvm,也可以是其他jvm或另一台机器)。通过直接打印ActorRef看到Actorpath,比如本例是/app/user/echoActor
像这种直接由system创建出来的Actor被称为顶层Actor,一般系统设计的时候,顶层Actor数量往往不会太多,大都由顶层Actor通过getContext().actorOf()派生出来其他的Actor

Actor间的相互调用(tell, ask)

Actor模型中,Actor本身的执行是不占用被调用方(akka中的话是消息的发送者)的CPU时间片,所以,akkaActor在相互调用时均是异步的行为。

  • tell 发送一个消息到目标Actor后立刻返回
  • ask 发送一个消息到目标Actor,并返回一个Future对象,可以通过该对象获取结果。但前提是目标Actor会有Reply才行,如果没有Reply,则抛出超时异

Tell: Fire-forget

target.tell(message, getSelf());

其中第二个参数是发送者。之所以要带上这个是为了方便target处理完逻辑后,如果需要返回结果,可以也通过tell异步通知回去。

Ask: Send-And-Recieve-Future

Future<Object> future = Patterns.ask(echoActor, "echo me", 200);
future.onSuccess(new OnSuccess<Object>() {
    @Override
    public void onSuccess(Object result) throws Throwable {
        System.out.println(result);
    }
}, system.dispatcher());
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值