Upload
cooldaemon
View
2.376
Download
5
Embed Size (px)
Citation preview
Actor とエラーハンドリング~Erlang 時々 Scala~
M.Ikuta(@cooldaemon)Sep.4,2011
1
自己紹介
決済代行会社のプログラマ
某大手クーポンサイトの決済システム
iPhone + ScanJacket
Erlang 基礎勉強会や分散処理勉強会の主催
2
モチベーション何故、エラーハンドリングの知識が必要か?
堅牢なシステムを構築したい
休日に家族サービスができる
3
モチベーション何故、エラーハンドリングの知識が必要か?
堅牢なシステムを構築したい
休日に家族サービスができる
3DS の稟議が通る
3
モチベーション
並行や分散を取り入れるとシステムが複雑に?
並行や分散だからこそ堅牢なシステムを作れる!
4
本日のお題Erlang と Scala の紹介
Actor モデル
リンクによる相互監視
Supervisor Tree
Error Logger
例外
5
本日のお題Erlang と Scala の紹介
Actor モデル
リンクによる相互監視
Supervisor Tree
Error Logger
例外
6
Erlang と Scala の紹介
何故、Actor モデルの話をするために Erlang と Scala を選んだのか?
私が他の Actor モデルを実装したライブラリや言語を知らない
本日、話す予定のリンクによる相互監視が、他の Actor 実装に採用されているか不明
7
Erlang と Scala の紹介Erlang
ネットワークサーバを作るための DSL
並行と分散が得意
高い耐障害性
稼働率 99.9999999% も夢ではない
8
Erlang と Scala の紹介Erlang
Yaws, Mochiweb, RabbitMQ, CouchDB, Hibari, Riak, Kai, Scalaris, Ejabberd, etc..Tsung や BashoBench のような負荷試験ツールも作りやすい
モジュールや関数を物理的に離れたノードに転送できるので MapReduce なども得意
9
Erlang と Scala の紹介Scala
様々な言語の長所を集めた次世代言語
夢と希望が詰ってる
並行処理に関連するキーワードだけでも…
Thread, Actor, 部分継続, 並列コレクション, 非同期IO, CAS, STM, etc..
10
Erlang と Scala の紹介Scala
選択肢が多く、組み合わせも自由
Actor + STM
Actor + 継続
Actor + 非同期IO
継続 + 非同期IO
11
本日のお題Erlang と Scala の紹介
Actor モデル
リンクによる相互監視
Supervisor Tree
Error Logger
例外
12
Actor モデル
13
Actor モデル並行に動作する計算実体
13
Actor モデル並行に動作する計算実体
もう少し詳しい話をこれからするので、知ってる人は寝てて OK
13
Actor モデル世の中の全ては Actor である
全ての Actor は並行に動作する
Actor は、個々にローカルメモリを持ち、Actor 間でメモリ共有を行わない
Actor は、自分自身や他の Actor とメッセージを送受信しながら処理を行う
14
Actor モデルActor は、メッセージを受信するためにメールアドレスとメールボックスを持つ
メッセージは、メールアドレス宛に送信される
メッセージは、メールボックスに格納される
メッセージは必ず届いて処理される
15
Actor モデルメッセージの送信は非同期に行われる
メッセージ受信の順番は保証されていない
メールボックスから任意のメッセージを取り出せる
Actor は、新たな Actor を作成できる
16
Actor モデルErlang と Scala には実装されていないが…
Actor はノードを越えて移動できる
暇なノードへ働きに行ったり
壊れたノードから逃げたり
17
Actor モデル
Mailbox ActorReceiveMessage Message
Mailbox Actorreceivemessage messageSend
Mailbox ActorCreate
18
本日のお題Erlang と Scala の紹介
Actor モデル
リンクによる相互監視
Supervisor Tree
Error Logger
例外
19
リンクのよる相互監視リンク
二つの Actor 間のエラー伝播経路を定義
二つの Actor がリンクされている場合、一方の Actor が停止すると、もう一方に EXIT シグナルが送られる
20
リンクのよる相互監視EXIT シグナル
Actor が停止する際に自動的に生成される(故意に生成する事もできる)
停止する Actor とリンクしている全ての Actor へブロードキャストされる
EXIT シグナルには停止理由が含まれる
21
リンクのよる相互監視
EXIT
LinkA B
A B
A B
A
22
リンクのよる相互監視
EXITEXIT
A B C
A B C
A C
23
リンクのよる相互監視
EXIT
EXIT
A B C
A B C
A B
A
24
リンクのよる相互監視EXIT シグナル
EXIT シグナルを受信した Actor は、trap_exit が true か否かで動作が異なる
Erlang では、trap_exit が true の Actor をシステムプロセスと呼ぶ
25
リンクのよる相互監視システムプロセス(Erlang)
trap_exit 停止理由 動作
TRUE kill 停止:killed をブロードキャスト
TRUE X {'EXIT', Pid, X} をメールボックスに追加
FALSE normal 無視
FALSE kill 停止:killed をブロードキャスト
FALSE X 停止:X をブロードキャスト
26
リンクのよる相互監視システムプロセス(Scala)
trap_exit 停止理由 動作
TRUE X Exit(Actor, X) をメールボックスに追加
FALSE 'normal 無視
FALSE X 停止:X をブロードキャスト
27
リンクのよる相互監視リンクの利点
故障箇所を Actor (やノード)に隔離できる
大怪我ではなく、擦り傷で済む
依存関係がある Actor をまとめて停止できる
一方がシステムプロセスであれば、停止を検知してエラー処理を行える
28
リンクのよる相互監視リンクの利点
リンクはノードを越えて行える
監視 Actor と Worker Actor を、それぞれ、物理的に離れた別ノードに配置できる
障害が発生した信頼できない Actor(やノード)にエラー処理を任せない
29
リンクのよる相互監視エラー処理は…
監視している Actor が処理を引き継ぐ
停止した Actor を再起動
処理を引き継ぐ Actor を別ノードに作る
社内監視システムにエラー通知を行う
etc…
30
リンクのよる相互監視リンクの利点
コードがスッキリする
31
リンクのよる相互監視JavaScript
if (is_success()) { do_samething();} else { throw "Exception";}
32
リンクのよる相互監視Erlang
ok = is_success(),do_samething().
ok 以外で例外 {badmatch, 戻り値} が発生
33
リンクのよる相互監視JavaScript
var num = get_number();switch (num) { case 1: do_samething1(); break; case 2: do_samething2(); break; default: throw "Exception: " + num; break;}
34
リンクのよる相互監視Erlang
case get_numer() of 1 -> do_samething1(); 2 -> do_samething2()end.
1, 2 以外で例外 {case_clause, 戻り値} が発生
35
リンクのよる相互監視Erlang
do_samething(get_number()).do_samething(1) -> do_samething1();do_samething(2) -> do_samething2().
1, 2 以外で例外 {function_clause, 戻り値} が発生
36
リンクのよる相互監視Scala
getNumber() match { case 1 => doSamething1() case 2 => doSamething2()}
例外 scala.MatchError が発生するが、Actor 内ならリンク先に Exit(Actor, Exception)
37
リンクのよる相互監視リンクの利点
コードがスッキリする
異常事態を考慮したコードを書く必要がない
その場でウダウダせずに、システム全体の構造により頑健性を担保する
38
リンクのよる相互監視リンクの利点
コードがスッキリする
とは言え…回復不能な想定外の異常事態が発生した場合の処理のみ省略する事!!
39
本日のお題Erlang と Scala の紹介
Actor モデル
リンクによる相互監視
Supervisor Tree
Error Logger
例外
40
Supervisor TreeActor リンクを木状に構成したもの
木の上位にある Actor(trap_exit=true)が下位の Actor を監視する
監視専用の Actor を Supervisor と呼ぶ
Erlang OTPAkka
41
Supervisor Tree個人的な設計原則
全ての Actor は Supervisor 配下に設置
Application:Supervisor Tree = 1:1
42
Supervisor Tree全ての Actor は Supervisor 配下に設置
Actor が孤独死するシステムは堅牢ではない
43
Supervisor TreeApplication:Supervisor Tree = 1:1
Supervisor を複数使いたい?
Root の Supervisor の下に、それらの Supervisor を設置して一元管理
44
Supervisor Tree
Worker
Supervisor
Worker Supervisor
Worker WorkerWorker
45
Supervisor TreeSupervisor の仕事
配下の Actor の起動と停止に特化
他の余計な仕事は行わない
46
Supervisor TreeSupervisor 毎の設定(抜粋)
停止した Actor のみ再起動(one_for_one)
停止した Actor と同じ Supervisor 配下の Actor を全て再起動(one_for_all)
47
Supervisor TreeSupervisor 毎の設定(抜粋)
一定の秒数以内に一定の回数以上 Worker の起動停止を繰り返したら Supervisor を終了
再起動しても何度も同じ理由で停止する状態を避ける
48
Supervisor TreeWorker 毎の設定(抜粋)
必ず再起動(permanent)
異常終了した場合だけ再起動(transient)
再起動しない(temporary)
終了処理のタイムアウト時間
49
本日のお題Erlang と Scala の紹介
Actor モデル
リンクによる相互監視
Supervisor Tree
Error Logger
例外
50
Error Loggerエラーハンドリングの仕組み
Erlang OTP
Erlang では、catch されなかった例外は Error Logger で処理される
OTP の Event Manager Behaviour で作られている
Erlang Behaviour = Scala Trait
51
Error LoggerEvent Manager
予め任意の Event に幾つかの Event Handler を登録しておくと、その Event が発生した際に、登録済みの複数の Event Handler を全て実行する
52
Error Loggerデフォルトで、エラーログを TTY に出力する Error Handler が登録されている
OTP の System Application Support Libraries(SASL) を起動すると…
エラーログをファイルに残す
エラーログファイルをローテションする
などの設定ができる Error Handler を追加する
53
Error LoggerSASL の Error Handler
速度を上げるため、バイナリ形式でログを残す
専用のログを読むアプリケーション(rb)を使用しないとログが読めない
エラーメッセージが少し解り難い
54
Error LoggerLagger
SASL が性に合わない人向け
Riak の Basho 製
解りやすいメッセージをテキスト形式でファイルに保存してくれる Handler が登録される
55
Error LoggerScala(提案)
Event Manager Trait を作る
Event Manager Trait を extends した Error Logger Actor を作る
Error Logger にメッセージを送る Trait を作る
56
本日のお題Erlang と Scala の紹介
Actor モデル
リンクによる相互監視
Supervisor Tree
Error Logger
例外
57
例外最後に Actor とは関係無いのですが、Erlang と Scala の例外についての余談をさせてください
58
例外Erlang
Erlang には三つの例外がある
error
throw
exit
59
例外Erlang
error
システムエラーであり、呼び出し側が対処できないエラーである場合に使用する
意図的に起こす事もできるが、パターンマッチの失敗等で自動的に発生する
error は catch 非推奨
60
例外Erlang
throw
呼び出し側が対処できるかもしれないエラーである場合に使用する
呼び出し側は、対処できないと判断した場合、無理に catch しなくとも良い
61
例外Erlang
exit
Actor を停止する際に使う
62
例外Erlang
try foo(), bar()catch error:foo -> handle_foo(); throw:bar -> handle_bar(); Class:Exception -> handle_error(Class, Exception)after baz()end.
63
例外Scala
チェック例外が無い
例外は、なるべく異常事態に限定する
Actor や STM の内部での利用は必要悪
Java の throw 宣言されているメソッドを使用する際、catch しなくともコンパイル時にエラーとはならない
64
例外Scala
回復可能な想定内のエラーは、Option や Either に包んで返す
Java メソッドの例外は、scala.util.control.Exception.allCatch で Option/Either に包む
65
例外Scala
import scala.util.control.Exception.allCatch
def foo(): Either[Throwable, Foo] = allCatch either {new JavaFoo}def bar(objFoo: Foo): Either[Throwable, Bar] = allCatch either {new JavaBar(objFoo)}
val result: Either[Throwable, Bar] = for { objFoo <- foo().right objBar <- bar(objFoo).right} yield objBar
66
ご清聴ありがとうございました
67