SRE サイトリライアビリティエンジニアリングを読んだり作ったもの
エラーバジェットとかリスク許容の話を見たくて、いまさらO’Reilly Japan - SRE サイトリライアビリティエンジニアリングを読んだ。 Googleの人が書いたエッセイ集的な側面もあるので、Googleの事故事例とかも書かれてて面白い。
PDF版を買ってメモをしながら読めるいい感じのPDFビューアがなかったので、以前作ったmu-pdf-viewerというPDFビューアを少し改善した。
Cmd+Shift+Cで見てるページを画像 + 代替えテキストでコピーできるようにした。
— azu (@azu_re) May 21, 2019
本読もうと思ったのに、まだ一行も読めてない。 pic.twitter.com/45BzXD4FID
Cmd + Shift+ Cで表示しているページとそのテキストをコピーできるようにして、OneNoteにスクショを貼りながらメモを取るスタイルにした。 (ページ全体だとちょっと大きいので選択範囲だけとかにもう少し絞りたい気がする。)
1章から3章にかけてエラーバジェットの話がいろいろあった。
#SRE本
— azu (@azu_re) May 22, 2019
エラーバジェットの主なメリットはプロダクト開発者とSREに共通の指標になるので、バランスが取りやすい。
エラーバジェットが付きかけているなら、リリース速度を下げるとかの調整ができる。
逆にどんどん入れたい場合は、エラーバジェットに余裕があるならリスクを多めに取れる。
どのぐらいの信頼性損ねても許容されるのかの指標 = エラーバジェットを使うことで、リリース速度のバランスを取るという話面白かった。 この辺はPerformanceだったりいろんなことにも言えそう。
「19章 フロントエンドにおけるロードバランシング」で、N
台のサーバがあるときにある id
のパケットに対してどのサーババランシングをするかという話。
単純に id % N
でも接続先を固定できそうだけど、サーバの台数が変わると N
が変わって接続先も変わってしまうという問題が出てくる。
このときに、サーバの台数 N
が変わっても同じハッシュ値を生成する方法としてコンシステントハッシュ法という話がでてきた。
アルゴリズムの説明読んでもイメージがしにくかったのでAssemblyScriptを使って実装してみた。 wasmバイナリで動くコンシステントハッシュ法を実装してみたけど、AssemblyScriptとかWebAssembly自体にいろいろハマった。
「22章 カスケード障害への対応」が結構面白かった。
#SRE本 カスケーディングな障害のパターン
— azu (@azu_re) May 25, 2019
1. サーバの過負荷
2. リソースの枯渇
さらにサーバが過負荷状態で応答しなくなったときに、クラアント側でリトライ処理が行われていると更に悪化することがある。
Exponential Backoffの実装とかリトライバジェットを実装するhttps://t.co/aXgJ4QfZje
#SRE本 過負荷時
— azu (@azu_re) May 25, 2019
- 品質を落として返す
- バックグラウンドのタスクチェック
- キャパシティを一時的に追加する
- ヘルスチェック L4とL7の区別
- リトライ処理はExponential Backoff
- トラフィックを落とすのは最終段階
- 1つの障害を別の障害と交換しないように
- 再起動によって被害拡大を避ける
この中で、クライアントではExponential backoffでのリトライをしないとサーバ側が過負荷のときにサーバにリクエストが飛びまくって被害が拡大するという話がでてきた。 Exponential backoffな実装はしたことがあるけど、ライブラリ書いたことがなかったので書いてみた。
次のようにDurationがExponentialな値を返すGeneratorを作ることで、Async/Awaitと組み合わせてExponential backoffなリトライができるデザインにしてみた。
import { generateBackoff } from "exponential-backoff-generator";
const doAsyncTask = async () => {
const backoff = generateBackoff();
for (const { sleep } of backoff) {
try {
return await YourAsyncTaskWantToRetry();
} catch(error) {
await sleep(); // wait 100ms, 200ms, 400ms, 800ms ...
}
}
throw new Error("YourAsyncTaskWantToRetry failed at all");
};
doAsyncTask().then(result => {
console.log(result); // YourAsyncTaskWantToRetry resolved value
}).catch(error => {
console.error(error); // Error: YourAsyncTaskWantToRetry failed at all
});
元ネタはRustのyoshuawuyts/exponential-backoff: Exponential backoff generator with jitter.。
「26章 データの完全性:What You Read Is What You Wrote」のデータの完全性とはなにかという話が良かった
#SRE本 「データの完全性とはクラウドのサービスがユーザーからアクセス可能であること。ユーザーからのデータアクセスは特に重要なので、このアクセスは完全な形を保っていなければならない」
— azu (@azu_re) May 26, 2019
一時的でもデータが表示されないと、データ自体は消えてなくてもユーザーはデータが消えたと思ってしまう
リストアのためのバックアップであって逆ではないよという話が面白かった。 この完全性の話は「22章 カスケード障害への対応」と比べながら読むといいのかなと思った。
あとこの章はGoogleで実際におきたデータを削除する障害から復帰までの話とかがあってよかった。
#SRE本 これはホラーだ。解決までのプロセスもめっちゃ辛い感じになってる。実際にテープからリストアするの物理的に大変そうだ。
— azu (@azu_re) May 26, 2019
トラック配送とかの単語がでてくるのやばいな…
完全には戻せなかった事例でもあるのか pic.twitter.com/pvk1eeBlrw
第Ⅲ部 実践は全体的に読み物として面白い話が多くてよかった。
その他
- モニタリングシステムは次の2つを答えるものになってないといけない
- 何が壊れたのか(症状)
- なぜそれが壊れたか(原因)
- ポストモーテムはどの部分を改善できるかを提案する
- 継続的なリカバリ検証
- 運用の一部として継続的にリカバリプロセスのテストをする
お知らせ欄
JavaScript Primerの書籍版がAmazonで購入できます。
JavaScriptに関する最新情報は週一でJSer.infoを更新しています。
GitHub Sponsorsでの支援を募集しています。