第13回のオンライン輪読会に備えて読んだ内容を自分なりにまとめておく。
今回の記事はこちら。
[期待/予想する内容]
この記事の目次は次のとおりである。
- はじめに
- 分散システムのタイプ
- ハードリアルタイムシステムは奇妙です
- ネットワークを介したメッセージの要求/応答
- ハードリアルタイム分散システムでの障害モードの処理
- ハードリアルタイム分散システムのテスト
- 未知のものを未知のものとして扱う
- ハードリアルタイム分散システムの群れ
- 分散バグはしばしば潜んでいます
- 分散システムの問題のまとめ
「分散システムのタイプ」……パッと思いつくのは、同期でリクエストを処理するタイプと、非同期で処理するタイプ、の2つかな。でもこのあとの目次で「ハードリアルタイム分散システム」って単語が出てきてるから、同期か非同期かっていう分類ではない気もする。ハードリアルタイムってなんだ……極度の同時刻性が求められるってことか?
「ハードリアルタイムシステムは奇妙です」……いきなり奇妙ですと言われても。なんだこれ。ちょっと内容が想像つかない。
「ネットワークを介したメッセージの要求/応答」……ネットワークを介した分散システムを、如何にリアルタイムに近づけるか、って戦略の話だろうか。たとえばキャッシュとか、並列リクエストとか。
「ハードリアルタイム分散システムでの障害モードの処理」……障害モードってなんだろう。これまでのThe Amazon Builders' Libraryの用語的には、障害発生時の挙動ってことかな。ちょっと性能を落として動作させるとか。リアルタイム性が要求される場合に障害があると辛そう。そういう処理はあまり経験がないので、どういう処理をするのか気になる。
「ハードリアルタイム分散システムのテスト」……テストは想像する以上に大変そう。TLA+とか使うんだろうか。あとは、本番環境に限りなく近づけた環境でのE2Eテストとか、本番環境で一部のリクエストをコピーしてテストするとか。
「未知のものを未知のものとして扱う」……これはどういうことだろう。対向システムからの知らないレスポンスだったらエラーとして処理するように実装する、とかそういうことだろうか。
「ハードリアルタイム分散システムの群れ」……群れ。フリート。1台じゃないからカナリアリリースみたいなテストが
「分散バグはしばしば潜んでいます」……テストの話とは別にバグの話がある。本番環境で見つけた時に、どう回復させるか、リカバリするかとかそういう話だろうか。
「分散システムの問題のまとめ」……ここだけでも読む価値がありそう。あとは気になるトピックだけつまみ食いするとかしても良いかも。
[記事の要約]
次に、実際に記事を読んだ内容を箇条書きでまとめる。
はじめに
- 分散システム:サーバーが2台以上
- 分散システムの課題:レイテンシー、スケーリング、ネットワーキング API の理解、データのマーシャリングとアンマーシャリング、および Paxos などのアルゴリズムの複雑さ
- 相互に関連する2つの問題:独立した障害と非決定性
- 何がどう失敗したかをしることは困難
分散システムのタイプ
- 3つのスペクトラム:オフライン分散システム、ソフトリアルタイム分散システム、ハードリアルタイム分散システム
- オフライン:バッチ処理システム、ビッグデータ分析クラスター、映画シーンレンダリングファーム、タンパク質フォールディングクラスターなど
- 分散処理の利点(スケーラビリティとフォールトトレランス)あり、欠点(複雑な障害モードと非決定性)なし
- ソフトリアルタイム:検索インデックスビルダー、障害のあるサーバーを探すシステム、Amazon EC2のロールなど
- 継続的に結果を更新するが、10分から数時間オフラインになりうる
- ハードリアルタイム:フロントエンドウェブサーバー、注文パイプライン、クレジットカードトランザクション、すべての AWS API、電話など
ハードリアルタイムシステムは奇妙です
ネットワークを介したメッセージの要求/応答
- ネットワーク呼び出し:メソッド呼び出し1つが独立して失敗しうる8ステップに
- 単一マシン(ドメイン)上の
find()
の失敗原因:CPUオーバーヒート、マシンの電源故障、カーネルパニック、メモリやディスク不足、放射線によるRAM誤作動など - ユニットテストではこれらのケースはカバーされていないし、する意味もない
- マシン全体で運命を共有:対処すべき障害モードを減らしてくれる
ハードリアルタイム分散システムでの障害モードの処理
- サーバーとネットワークはマシンと運命を共有せず:ネットワーク障害のテスト必要
- 障害原因:中間ルーターのクラッシュ、サーバーのクラッシュ、ネットワークカードの故障など
- 8つすべての障害モードに対応:1行のコードに15行追加、複雑!
ハードリアルタイム分散システムのテスト
- 単一マシンのテスト:オブジェクトの異なる状態のテスト、比較的簡単
- ハードリアルタイムのテスト:失敗パターンが増えるので、テストマトリックスが激増
- オブジェクト呼び出し4回×呼び出し結果5パターン×10シナリオ=200パターン
- サーバー側のテストも同じ複雑なパターンでテスト必要:テストしない限り分からない
未知のものを未知のものとして扱う
- 可能性のある障害をすべて考慮することは不可能
- UNKNOWNエラー:要求は成功したかもしれないし失敗したかもしれない
- 再試行すべき?何回?間隔は?:
- 副作用がある場合の再試行は悪夢
ハードリアルタイム分散システムの群れ
- 分散システムの複数の抽象化レベル:個々のマシン、マシンのグループ(AZ)、グループのグループ(リージョン)、その他
- 再帰的分散エンジニアリング:グループ間で前述のネットワーク障害発生
- グループ間の失敗のテスト、マシン間での失敗のテストが必要
- バグは表面化するまで時間がかかる、隣接システムにも予測できない影響を与える可能性
分散バグはしばしば潜んでいます:分散バグの流行
- 一般常識:障害は早く発生する方がよい、特に本番稼働前に
- ネットワーク障害を処理できなかった場合におきる分散バグは深刻:他のマシンに広がる可能性高
- Amazon全体の障害
- カタログサーバーのディスクフル時のエラー処理ミス
- 空のレスポンスが返る
- 高速なのでロードバランサからのリクエストが集中
- 製品情報が表示されずサイト全体がダウン
分散システムの問題のまとめ
- 分散システムのエンジニアリングは困難
- 考慮すべきエラーパターンが膨大
- UNKNOWNが返るネットワーク操作
- 複数の分散レベル:低レベルの物理マシン〜リージョンレベル
- バグはデプロイ後出現まで時間がかかり、かつ影響範囲大
- 上記はネットワークの物理法則によるので変更できない
- 分散システムを管理する様々な方法がThe Amazon Builder's Libraryで公開されている
[予想のふりかえりなど]
分散システムのタイプ、同期か非同期かという予想は割と合ってた。ただし、スペクトラムという用語が使われていることから考えると、単純な同期/非同期、オフライン/オンラインの二元論で問題を考えるよりは、連続的な性質として捉えた方が良さそう。
ネットワークを介したメッセージのやりとりの複雑性は多少意識しないこともないが、AWS SDKに基本任せてしまうことが多いので改めて勉強になった。また、単一マシンの障害パターンでガンマ線の話が登場したりして、これはもうソフトウェアエンジニアには手が出せないな……と感じた。
未知のもの、結局どう取り扱うのがいいんだろうか。副作用がある場合は、リトライ前にステータスチェックするような処理を挟むとか?でもその処理すらも失敗する可能性があるわけで……。状態の管理が、単一マシンの場合と比べて圧倒的に複雑になるというのはよくわかるな。
分散バグのAmazonダウンのエピソードは、以前読んだ『ヘルスチェックの実装』の回で対策まで含めて紹介されていたし、ハードリアルタイム分散システムの群れの部分の説明は、『アベイラビリティーゾーンを使用した静的安定性』の回を思い出させる。UNKNOWN以外のエラータイプのリトライは、『ジッターを伴うタイムアウト、再試行、およびバックオフ』の回でやった内容を思い出した。
最後のまとめを読むと、この記事を最初に読めば良かったかも、と思った。
[まとめ]
- 「The Amazon Builder's Library」の『分散システムの課題』を読んだ
- 分散システムの課題が包括的に示されており、The Amazon Builder's Libraryの中で最初に読むべき記事とも言える
- 個々の課題への対策については各記事で紹介されているので、この記事を読んで気になるテーマがあったら該当する記事を読むと良さそう
これで2020年4月現在で公開されている13記事をすべて読んだ!🎉
あとは実践あるのみ。💪