Mercurial > hg > Members > anatofuz > slides
comparison slides/20170116/slide.md @ 2:1d0f0dcfda28
modified slide directory
author | Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 16 Jan 2018 21:00:07 +0900 |
parents | 20170116/slide.md@ac148561d3ef |
children |
comparison
equal
deleted
inserted
replaced
1:ac148561d3ef | 2:1d0f0dcfda28 |
---|---|
1 title: 分散フレームワークakkaの調査 | |
2 author: Takahiro Shimizu | |
3 profile: | |
4 lang: Japanese | |
5 | |
6 | |
7 # 調査目的 | |
8 * 先輩の修論の比較材料の為に行う | |
9 * 分散フレームワークの1つであるakkaがどのような書き方、及び処理なのかを調査する | |
10 | |
11 # 調査内容 | |
12 * akkaのmac osx,ubuntu上の導入 | |
13 * [公式チュートリアル](https://developer.lightbend.com/guides/akka-quickstart-java/)の例題を行う | |
14 * 今回はJavaで実行した | |
15 | |
16 # 環境構築 | |
17 | |
18 * 公式からzipファイルで提供されているので落とす | |
19 * 例題はGradleで実行できるように作成されているので `$ gradle run` を実行可能. | |
20 | |
21 # akkaの分散処理 | |
22 | |
23 * akkaはアクターモデルを採用したフレームワーク | |
24 * アクターモデルでは「アクター」と呼ばれるオブジェクト同士がメッセージ通信を行うことで並列処理を実現する(イベント・ドリブン) | |
25 * publicなAPIを持っていない為,強力な分離機能を持っており、複数のJVMなどでも連携可能 | |
26 * 環境透過性 | |
27 * 軽量 | |
28 * JVM上で動き、ScalaとJavaをサポートしている | |
29 | |
30 # 例題(Hello,World) | |
31 | |
32 * 今回は公式チュートリアルにある、複数のアクターが挨拶をするHello Worldの例題を実行する | |
33 * <img src="https://developer.lightbend.com/guides/akka-quickstart-java/images/hello-akka-architecture.png"> | |
34 | |
35 * 実行結果 | |
36 | |
37 ``` | |
38 $ gradle run | |
39 Starting a Gradle Daemon (subsequent builds will be faster) | |
40 | |
41 > Task :run | |
42 >>> Press ENTER to exit <<< | |
43 [INFO] [01/16/2018 15:33:05.871] [helloakka-akka.actor.default-dispatcher-4] [akka://helloakka/user/printerActor] Howdy, Akka | |
44 [INFO] [01/16/2018 15:33:05.872] [helloakka-akka.actor.default-dispatcher-4] [akka://helloakka/user/printerActor] Howdy, Lightbend | |
45 [INFO] [01/16/2018 15:33:05.872] [helloakka-akka.actor.default-dispatcher-4] [akka://helloakka/user/printerActor] Good day, Play | |
46 [INFO] [01/16/2018 15:33:05.872] [helloakka-akka.actor.default-dispatcher-4] [akka://helloakka/user/printerActor] Hello, Java | |
47 ``` | |
48 | |
49 # Hello World Actors | |
50 | |
51 * 例題のActorrは3種類のmessageを利用する | |
52 | |
53 * `WhoToGreet` | |
54 * greetingの受取用オブジェクト | |
55 * `Greet` | |
56 * greetingの実行用 | |
57 * `Greeting` | |
58 * `greeting`にメッセージを含める為の命令 | |
59 | |
60 * 複数のスレッドで共有をする必要がある為、メッセージはimmutableでなければならない | |
61 | |
62 | |
63 # Greeter Actor | |
64 | |
65 * `Greeter` のコンストラクタは、送信用メッセージと出力用のActorのリファレンスを必要とする | |
66 * mainの中ではGreeterは複数呼ばれている | |
67 | |
68 ``` | |
69 package com.lightbend.akka.sample; | |
70 | |
71 import akka.actor.AbstractActor; | |
72 import akka.actor.ActorRef; | |
73 import akka.actor.Props; | |
74 import com.lightbend.akka.sample.Printer.Greeting; | |
75 | |
76 public class Greeter extends AbstractActor { | |
77 static public Props props(String message, ActorRef printerActor) { | |
78 return Props.create(Greeter.class, () -> new Greeter(message, printerActor)); | |
79 } | |
80 | |
81 static public class WhoToGreet { | |
82 public final String who; | |
83 | |
84 public WhoToGreet(String who) { | |
85 this.who = who; | |
86 } | |
87 } | |
88 | |
89 static public class Greet { | |
90 public Greet() { | |
91 } | |
92 } | |
93 | |
94 private final String message; | |
95 private final ActorRef printerActor; | |
96 private String greeting = ""; | |
97 | |
98 public Greeter(String message, ActorRef printerActor) { | |
99 this.message = message; | |
100 this.printerActor = printerActor; | |
101 } | |
102 | |
103 @Override | |
104 public Receive createReceive() { | |
105 return receiveBuilder() | |
106 .match(WhoToGreet.class, wtg -> { | |
107 this.greeting = message + ", " + wtg.who; | |
108 }) | |
109 .match(Greet.class, x -> { | |
110 printerActor.tell(new Greeting(greeting), getSelf()); | |
111 }) | |
112 .build(); | |
113 } | |
114 } | |
115 ``` | |
116 | |
117 # Printer Actor | |
118 | |
119 * `Logging.getLogger(getContext().getSystem(), this);` で各Actorが `log.info()` に追記していく | |
120 * `Greeting` とlogsに対してhandleを所持している | |
121 | |
122 ``` | |
123 package com.lightbend.akka.sample; | |
124 | |
125 import akka.actor.AbstractActor; | |
126 import akka.actor.ActorRef; | |
127 import akka.actor.Props; | |
128 import akka.event.Logging; | |
129 import akka.event.LoggingAdapter; | |
130 | |
131 public class Printer extends AbstractActor { | |
132 static public Props props() { | |
133 return Props.create(Printer.class, () -> new Printer()); | |
134 } | |
135 | |
136 static public class Greeting { | |
137 public final String message; | |
138 | |
139 public Greeting(String message) { | |
140 this.message = message; | |
141 } | |
142 } | |
143 | |
144 private LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this); | |
145 | |
146 public Printer() { | |
147 } | |
148 | |
149 @Override | |
150 public Receive createReceive() { | |
151 return receiveBuilder() | |
152 .match(Greeting.class, greeting -> { | |
153 log.info(greeting.message); | |
154 }) | |
155 .build(); | |
156 } | |
157 } | |
158 ``` | |
159 | |
160 | |
161 # Actorを作る | |
162 | |
163 * akkaはインスタンスを作る際に `new` を使わない。これはakkaのインスタンスがリファレンスである為 (`akka.actor.ActorRef`)である。 | |
164 * その為、軽量かつ柔軟にシステムに組み込むことが可能である | |
165 * akkaのActorは `akka.actor.ActorSystem` が管理する。(factoryなどとも呼ばれる) | |
166 * 例題では次のようにakkaのインスタンスを作成している。 | |
167 | |
168 ``` | |
169 public class AkkaQuickstart { | |
170 public static void main(String[] args) { | |
171 final ActorSystem system = ActorSystem.create("helloakka"); | |
172 try { | |
173 //#create-actors | |
174 final ActorRef printerActor = | |
175 system.actorOf(Printer.props(), "printerActor"); | |
176 final ActorRef howdyGreeter = | |
177 system.actorOf(Greeter.props("Howdy", printerActor), "howdyGreeter"); | |
178 final ActorRef helloGreeter = | |
179 system.actorOf(Greeter.props("Hello", printerActor), "helloGreeter"); | |
180 final ActorRef goodDayGreeter = | |
181 system.actorOf(Greeter.props("Good day", printerActor), "goodDayGreeter"); | |
182 //#create-actors | |
183 ``` | |
184 | |
185 # メッセージ送信 | |
186 | |
187 * akkaのメッセージ送信は `ActorRef`の`tell`メソッドを呼ぶ。 | |
188 | |
189 ``` | |
190 howdyGreeter.tell(new WhoToGreet("Akka"), ActorRef.noSender()); | |
191 howdyGreeter.tell(new Greet(), ActorRef.noSender()); | |
192 | |
193 howdyGreeter.tell(new WhoToGreet("Lightbend"), ActorRef.noSender()); | |
194 howdyGreeter.tell(new Greet(), ActorRef.noSender()); | |
195 | |
196 helloGreeter.tell(new WhoToGreet("Java"), ActorRef.noSender()); | |
197 helloGreeter.tell(new Greet(), ActorRef.noSender()); | |
198 | |
199 goodDayGreeter.tell(new WhoToGreet("Play"), ActorRef.noSender()); | |
200 goodDayGreeter.tell(new Greet(), ActorRef.noSender()); | |
201 ``` | |
202 | |
203 * `Greeter` Actrorは `Printer` Actorにメッセージを送信している | |
204 | |
205 ``` | |
206 printerActor.tell(new Greeting(greeting), getSelf()); | |
207 ``` | |
208 | |
209 # テスト | |
210 | |
211 * Javaで使われているのでテストはJUnitを利用できる | |
212 * akkaaでは `akka.test.javadsl.TestKit` が用意されており, TestKit が推奨されている。 | |
213 * 詳しくは[公式ドキュメント](https://doc.akka.io/docs/akka/current/testing.html?language=java)を見ろということらしい… | |
214 | |
215 ``` | |
216 `ckage com.lightbend.akka.sample; | |
217 | |
218 import akka.actor.ActorRef; | |
219 import akka.actor.ActorSystem; | |
220 import akka.testkit.javadsl.TestKit; | |
221 import com.lightbend.akka.sample.Greeter.*; | |
222 import com.lightbend.akka.sample.Printer.*; | |
223 | |
224 import static org.junit.Assert.assertEquals; | |
225 | |
226 import org.junit.AfterClass; | |
227 import org.junit.BeforeClass; | |
228 import org.junit.Test; | |
229 | |
230 public class AkkaQuickstartTest { | |
231 static ActorSystem system; | |
232 | |
233 @BeforeClass | |
234 public static void setup() { | |
235 system = ActorSystem.create(); | |
236 } | |
237 | |
238 @AfterClass | |
239 public static void teardown() { | |
240 TestKit.shutdownActorSystem(system); | |
241 system = null; | |
242 } | |
243 | |
244 @Test | |
245 public void testGreeterActorSendingOfGreeting() { | |
246 final TestKit testProbe = new TestKit(system); | |
247 final ActorRef helloGreeter = system.actorOf(Greeter.props("Hello", testProbe.getRef())); | |
248 helloGreeter.tell(new WhoToGreet("Akka"), ActorRef.noSender()); | |
249 helloGreeter.tell(new Greet(), ActorRef.noSender()); | |
250 Greeting greeting = testProbe.expectMsgClass(Greeting.class); | |
251 assertEquals("Hello, Akka", greeting.message); | |
252 } | |
253 } | |
254 ``` |