沧海一粟

天下事有难易乎?为之,则难者亦易矣;不为,则易者亦难矣。

0%

akka笔记

Akka is a toolkit and runtime for building highly concurrent, distributed, and fault-tolerant event-driven applications on the JVM. Akka can be used with both Java and Scala. This guide introduces Akka by describing the Java version of the Hello World example. If you prefer to use Akka with Scala, switch to the Akka Quickstart with Scala guide.

Actors are the unit of execution in Akka. The Actor model is an abstraction that makes it easier to write correct concurrent, parallel and distributed systems. The Hello World example illustrates Akka basics. Within 30 minutes, you should be able to download and run the example and use this guide to understand how the example is constructed. This will get your feet wet, and hopefully inspire you to dive deeper into the wonderful sea of Akka!

解决了什么问题

Akka是Actor模型的一种实现
Actor模型解决了 传统编程假设与现代多线程、多CPU架构的现实之间的不匹配问题。

  1. 消息传递的使用避免了锁和阻塞。
  2. Actor能够优化地处理错误情况。

Usage of message passing avoids locking and blocking.
Actors handle error situations gracefully

OOP在构建苛刻需求的分布式系统会遇到的问题

  1. 并发情况下封装导致效率问题和死锁问题。
  2. 并发时共享内存失效(CPU缓存失效导致)导致效率低的问题。
  3. 调用栈导致的后台线程在异常时的通信问题以及后续问题。
  1. The challenge of encapsulation
  2. The illusion of shared memory on modern computer architectures
  3. The illusion of a call stack

入门

After trying this example the comprehensive Getting Started Guide is a good next step to continue learning more about Akka.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
bogon:akka-quickstart-java weikeqin1$
bogon:akka-quickstart-java weikeqin1$ mvn compile exec:exec
[INFO] Scanning for projects...
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/plugins/maven-compiler-plugin/3.5.1/maven-compiler-plugin-3.5.1.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/plugins/maven-compiler-plugin/3.5.1/maven-compiler-plugin-3.5.1.pom (10 kB at 15 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/plugins/maven-compiler-plugin/3.5.1/maven-compiler-plugin-3.5.1.jar
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/plugins/maven-compiler-plugin/3.5.1/maven-compiler-plugin-3.5.1.jar (50 kB at 138 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/mojo/exec-maven-plugin/1.6.0/exec-maven-plugin-1.6.0.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/mojo/exec-maven-plugin/1.6.0/exec-maven-plugin-1.6.0.pom (13 kB at 65 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/mojo/exec-maven-plugin/1.6.0/exec-maven-plugin-1.6.0.jar
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/mojo/exec-maven-plugin/1.6.0/exec-maven-plugin-1.6.0.jar (58 kB at 179 kB/s)
[INFO]
[INFO] ------------------------< hello-akka-java:app >-------------------------
[INFO] Building app 1.0
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-actor-typed_2.13/2.6.6/akka-actor-typed_2.13-2.6.6.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-actor-typed_2.13/2.6.6/akka-actor-typed_2.13-2.6.6.pom (2.6 kB at 11 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-slf4j_2.13/2.6.6/akka-slf4j_2.13-2.6.6.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-slf4j_2.13/2.6.6/akka-slf4j_2.13-2.6.6.pom (2.9 kB at 7.9 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-actor-testkit-typed_2.13/2.6.6/akka-actor-testkit-typed_2.13-2.6.6.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-actor-testkit-typed_2.13/2.6.6/akka-actor-testkit-typed_2.13-2.6.6.pom (3.6 kB at 12 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-testkit_2.13/2.6.6/akka-testkit_2.13-2.6.6.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-testkit_2.13/2.6.6/akka-testkit_2.13-2.6.6.pom (3.5 kB at 10 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-actor-typed_2.13/2.6.6/akka-actor-typed_2.13-2.6.6.jar
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-testkit_2.13/2.6.6/akka-testkit_2.13-2.6.6.jar
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-actor-testkit-typed_2.13/2.6.6/akka-actor-testkit-typed_2.13-2.6.6.jar
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-slf4j_2.13/2.6.6/akka-slf4j_2.13-2.6.6.jar
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-slf4j_2.13/2.6.6/akka-slf4j_2.13-2.6.6.jar (17 kB at 38 kB/s)
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-testkit_2.13/2.6.6/akka-testkit_2.13-2.6.6.jar (261 kB at 328 kB/s)
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-actor-testkit-typed_2.13/2.6.6/akka-actor-testkit-typed_2.13-2.6.6.jar (315 kB at 382 kB/s)
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/com/typesafe/akka/akka-actor-typed_2.13/2.6.6/akka-actor-typed_2.13-2.6.6.jar (1.2 MB at 1.1 MB/s)
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ app ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.5.1:compile (default-compile) @ app ---
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compiler-api/2.7/plexus-compiler-api-2.7.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compiler-api/2.7/plexus-compiler-api-2.7.pom (891 B at 3.2 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compiler/2.7/plexus-compiler-2.7.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compiler/2.7/plexus-compiler-2.7.pom (4.9 kB at 34 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compiler-manager/2.7/plexus-compiler-manager-2.7.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compiler-manager/2.7/plexus-compiler-manager-2.7.pom (711 B at 3.0 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compiler-javac/2.7/plexus-compiler-javac-2.7.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compiler-javac/2.7/plexus-compiler-javac-2.7.pom (792 B at 5.3 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compilers/2.7/plexus-compilers-2.7.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compilers/2.7/plexus-compilers-2.7.pom (1.4 kB at 3.1 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compiler-api/2.7/plexus-compiler-api-2.7.jar
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compiler-manager/2.7/plexus-compiler-manager-2.7.jar
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compiler-javac/2.7/plexus-compiler-javac-2.7.jar
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compiler-manager/2.7/plexus-compiler-manager-2.7.jar (4.7 kB at 30 kB/s)
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compiler-javac/2.7/plexus-compiler-javac-2.7.jar (19 kB at 113 kB/s)
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-compiler-api/2.7/plexus-compiler-api-2.7.jar (26 kB at 90 kB/s)
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 4 source files to /Users/weikeqin1/Downloads/akka-quickstart-java/target/classes
[INFO]
[INFO] --- exec-maven-plugin:1.6.0:exec (default-cli) @ app ---
SLF4J: A number (1) of logging calls during the initialization phase have been intercepted and are
SLF4J: now being replayed. These are subject to the filtering rules of the underlying logging system.
SLF4J: See also http://www.slf4j.org/codes.html#replay
[2020-06-13 22:44:03,567] [INFO] [akka.event.slf4j.Slf4jLogger] [helloakka-akka.actor.default-dispatcher-3] [] - Slf4jLogger started
>>> Press ENTER to exit <<<
[2020-06-13 22:44:03,660] [INFO] [com.example.Greeter] [helloakka-akka.actor.default-dispatcher-5] [akka://helloakka/user/greeter] - Hello Charles!
[2020-06-13 22:44:03,663] [INFO] [com.example.GreeterBot] [helloakka-akka.actor.default-dispatcher-3] [akka://helloakka/user/Charles] - Greeting 1 for Charles
[2020-06-13 22:44:03,663] [INFO] [com.example.Greeter] [helloakka-akka.actor.default-dispatcher-5] [akka://helloakka/user/greeter] - Hello Charles!
[2020-06-13 22:44:03,663] [INFO] [com.example.GreeterBot] [helloakka-akka.actor.default-dispatcher-3] [akka://helloakka/user/Charles] - Greeting 2 for Charles
[2020-06-13 22:44:03,663] [INFO] [com.example.Greeter] [helloakka-akka.actor.default-dispatcher-5] [akka://helloakka/user/greeter] - Hello Charles!
[2020-06-13 22:44:03,664] [INFO] [com.example.GreeterBot] [helloakka-akka.actor.default-dispatcher-5] [akka://helloakka/user/Charles] - Greeting 3 for Charles

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 23.459 s
[INFO] Finished at: 2020-06-13T22:44:16+08:00
[INFO] ------------------------------------------------------------------------
bogon:akka-quickstart-java weikeqin1$
bogon:akka-quickstart-java weikeqin1$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.example;

import akka.actor.typed.ActorSystem;

import java.io.IOException;
public class AkkaQuickstart {
public static void main(String[] args) {
//#actor-system
final ActorSystem<GreeterMain.SayHello> greeterMain = ActorSystem.create(GreeterMain.create(), "helloakka");
//#actor-system

//#main-send-messages
greeterMain.tell(new GreeterMain.SayHello("Charles"));
//#main-send-messages

try {
System.out.println(">>> Press ENTER to exit <<<");
System.in.read();
} catch (IOException ignored) {
} finally {
greeterMain.terminate();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.example;

import akka.actor.typed.ActorRef;
import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.*;

import java.util.Objects;

// #greeter
public class Greeter extends AbstractBehavior<Greeter.Greet> {

public static final class Greet {
public final String whom;
public final ActorRef<Greeted> replyTo;

public Greet(String whom, ActorRef<Greeted> replyTo) {
this.whom = whom;
this.replyTo = replyTo;
}
}

public static final class Greeted {
public final String whom;
public final ActorRef<Greet> from;

public Greeted(String whom, ActorRef<Greet> from) {
this.whom = whom;
this.from = from;
}

// #greeter
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Greeted greeted = (Greeted) o;
return Objects.equals(whom, greeted.whom) &&
Objects.equals(from, greeted.from);
}

@Override
public int hashCode() {
return Objects.hash(whom, from);
}

@Override
public String toString() {
return "Greeted{" +
"whom='" + whom + '\'' +
", from=" + from +
'}';
}
// #greeter
}

public static Behavior<Greet> create() {
return Behaviors.setup(Greeter::new);
}

private Greeter(ActorContext<Greet> context) {
super(context);
}

@Override
public Receive<Greet> createReceive() {
return newReceiveBuilder().onMessage(Greet.class, this::onGreet).build();
}

private Behavior<Greet> onGreet(Greet command) {
getContext().getLog().info("Hello {}!", command.whom);
//#greeter-send-message
command.replyTo.tell(new Greeted(command.whom, getContext().getSelf()));
//#greeter-send-message
return this;
}
}
// #greeter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.example;

import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.*;

public class GreeterBot extends AbstractBehavior<Greeter.Greeted> {

public static Behavior<Greeter.Greeted> create(int max) {
return Behaviors.setup(context -> new GreeterBot(context, max));
}

private final int max;
private int greetingCounter;

private GreeterBot(ActorContext<Greeter.Greeted> context, int max) {
super(context);
this.max = max;
}

@Override
public Receive<Greeter.Greeted> createReceive() {
return newReceiveBuilder().onMessage(Greeter.Greeted.class, this::onGreeted).build();
}

private Behavior<Greeter.Greeted> onGreeted(Greeter.Greeted message) {
greetingCounter++;
getContext().getLog().info("Greeting {} for {}", greetingCounter, message.whom);
if (greetingCounter == max) {
return Behaviors.stopped();
} else {
message.from.tell(new Greeter.Greet(message.whom, getContext().getSelf()));
return this;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.example;

import akka.actor.typed.ActorRef;
import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.*;

public class GreeterMain extends AbstractBehavior<GreeterMain.SayHello> {

public static class SayHello {
public final String name;

public SayHello(String name) {
this.name = name;
}
}

private final ActorRef<Greeter.Greet> greeter;

public static Behavior<SayHello> create() {
return Behaviors.setup(GreeterMain::new);
}

private GreeterMain(ActorContext<SayHello> context) {
super(context);
//#create-actors
greeter = context.spawn(Greeter.create(), "greeter");
//#create-actors
}

@Override
public Receive<SayHello> createReceive() {
return newReceiveBuilder().onMessage(SayHello.class, this::onSayHello).build();
}

private Behavior<SayHello> onSayHello(SayHello command) {
//#create-actors
ActorRef<Greeter.Greeted> replyTo =
getContext().spawn(GreeterBot.create(3), command.name);
greeter.tell(new Greeter.Greet(command.name, replyTo));
//#create-actors
return this;
}
}
1
2
Exception in thread "main" java.lang.IllegalArgumentException: Actor class [cn.wkq.java.akka.AkkaDemo$HelloActor] must be subClass of akka.actor.Actor or akka.actor.IndirectActorProducer.
at akka.actor.AbstractProps.validate(AbstractProps.scala:31)

Rferences

[1] 42 | Actor模型:面向对象原生的并发模型
[2] doc.akka.io/docs/akka/current
[3] akka-guide
[4] Why modern systems need a new programming model
[5] How the Actor Model Meets the Needs of Modern, Distributed Systems
[6] doc.akka.io/docs/akka/2.2/AkkaJava.pdf
[7] guides/akka-quickstart-java
[8] akka-quickstart-java
[9] sbt-idea
[10] 快速入门 Akka Java 指南