$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

アプリケーションは全員で監視する - 「入門 監視」を読んだ

最近話題になっていた「入門 監視」を読んだ。アプリケーションの監視をするための実践的なノウハウが詰まっていて非常に参考になる書籍だった。

入門 監視 ―モダンなモニタリングのためのデザインパターン

入門 監視 ―モダンなモニタリングのためのデザインパターン

この本では、アプリケーションを監視するための骨格となる考え方や、様々な層(フロントエンドからOSのメトリックまで)での監視の入れ方の実践的なノウハウ、さらには障害対応をスムーズに行うためのフローや障害の根本対応をチームで行えるようにするためのやり方まで書かれている。実践的なすぐに取り入れられるような内容が多く、「アプリケーションをどう監視したら良いか分からない!」「障害対応をもっとうまくやる方法はないのだろうか?」と思う人には参考になる部分が多いと思う。


個人的にこの本の中で一番良いなと思ったのは、

  • SREだけでなくアプリケーションエンジニアも含めたアプリケーションに関わる人全員で監視を考えていくことが大事
  • むしろアプリケーションエンジニアはそのアプリケーションに誰よりも詳しいはずなので、アプリケーション監視のデザインのための知識を誰よりも持っているはず

という話。最近僕のチームではSREがチーム内に所属するようになったためアプリケーションエンジニアにいろんな運用知見が伝えられた。それにより以前よりアプリケーションエンジニアも監視に詳しくなり自分たちで監視ルールを積極的に入れられるようになった。結果として、これまでアプリケーションの監視で漏れがあった部分が埋まってきていると感じている。この経験からこの本で書かれているような、アプリケーションエンジニアも含めて全員で監視を考えていくことに対する重要性に非常に共感できた

最近、監視はみんなでやろうという話を色んな場所で見かける一方、監視にアプリケーションエンジニアも携わるのが当たり前という認識が広まっているという状況にはまだまだなっていないなと感じている。そのためこの本をきっかけに、アプリケーションエンジニアとSREの監視に対する意識が統一され、監視を全員でやるのが当たり前という文化が広まると良いなと思った。


その他自分にとって参考になったのは以下のようなポイントだった。

  • 監視というとサーバのOSのメトリクスなどからやってしまいがちだが、できるだけユーザーに近いところから監視を始めるのが最適
    • HTTPのレスポンスコードやリクエスト時間など
  • 3章のインシデントの対応フローとインシデント対応の際に必要なロール。またアラートからその根本対応をするためのやり方


とにかく実践的な内容ですぐに取り入れられるので一読してみると良さそうです!

読書ノート

* 問題を解決するための適切なツールを組み合わせて使うのは良い。連携して使えないたくさんのツールを持つのはアンチパターン(例: ネットワークのレイテンシとアプリケーションのレスポンスの悪化を関連付けられない)。連携できて役割が異なるなら良い 343
* ツールは誰かが使っている、使っていたからという理由では選ばず、現在の状況で試し、評価することが重要 373
* オペレーションチームだけでなく全員が本番環境全体に責任を持つことが大事。ソフトウェアエンジニアはアプリケーションに誰よりも詳しいので、アプリケーション監視の仕組みをデザインするのには最高の場所にいる 426
	* 良い。実際にSREがチームに所属して、それによりアプリケーションエンジニアも監視を意識するようになった。それによりアプリケーションの監視の仕組み構築がもっと良くなったと感じる
* 監視サービスのコンポーネント: データ収集、データストレージ、可視化、分析とレポート、アラート 572
* データ収集の手法として、メトリクスとステータス情報を/healthに出力し、その出力を監視する手法がある 595
* まず監視を追加すべきなのは、ユーザがあなたのアプリケーションとやり取りをするところ 824
* 監視とは、あるシステムやそのシステムのコンポーネントの振る舞いや出力を観察しチェックし続ける行為。アラートは、この目的を達成するための1つの方法でしかない 938
* 誤報はとにかく減らそう。アラートをチューニングする簡単な方法が1つある。 1080
	* オンコール担当は前日に送られたすべてのアラートの一覧を作る
	* 一覧にひととおり目を通しながら、各アラートはどのように改善できるか、あるいはアラートを削除してしまえないか自問自答する
* 監視自体は何も修復してくれないので、基礎にあるシステムを改善する時間を持たなければならない 1107
	* オンコールシフト中、場当たり的対応をしていない時間は、システムの回復力や安定性に対して取り組むのをオンコール担当の役割にする
	* 前週のオンコールの際に収集した情報を元に、次の週のスプリント計画にシステムの回復性や安定性について取り上げる計画を立てる
* オンコールローテーションは出勤日に始めると、チーム内で引き継ぎがやりやすくなる 1107
* ソフトウェアエンジニアもオンコールのローテーションに入れる 1157
* インシデント管理のプロセス
	* 1. インシデントの認識(監視が問題を認識)
	* 2. インシデントの記録(インシデントに対して監視の仕組みが自動でチケットを作成)
	* 3. インシデントの診断、分類、解決、クローズ(オンコール担当がトラブルシュートし、問題を修正し、チケットにコメントや情報を添えて解決済みとする)
	* 4. 必要に応じて問題発生中にコミュニケーションを取る
	* 5. インシデント解決後、回復力を高めるための改善策を考える
	* s: 簡潔によくまとまっている
* 数分以上かかる本当のサービス停止には明確に定義された役割が重要 1157
	* 現場指揮官、書紀、コミュニケーション調整役、インシデント対応役(作業員)
	* s: 現場指揮官は最もアプリケーションに詳しい人(例えばテックリード)が適切、コミュニケーション調整役はマネージャ(例エンジニアリングマネージャ)が適切、書紀はだれでも、対応役は全員でやる
* フロントエンド監視にはリアルユーザ監視とシンセティック監視の2つのアプローチがある 1693
	* リアルユーザ監視とは実際のユーザトラフィックを監視のデータとして使うこと(Google Analyticsでのフロントエンド計測とか)
	* WebpageTest.orgのようなものはシンセティック監視
* Navigation Timing APIのタイムライン 1791
	* s: ブラウザのライフサイクルを知るのに非常に良い図
* フロントエンド監視では 1871
	* 実際のユーザが見ているページのロード時間を監視しよう
	* JavaScriptの例外を監視しよう
	* ページのロード時間をCIシステムから計測し続け、ロード時間が許容時間内に収まるようにしよう
* 分散トレーシングとは。リクエストに一意なリクエストIDを「タグ付け」することで、そのリクエストがどのサービスにアクセスしたか、各サービスでどのくらいの時間を過ごしたかが分かる 2290
* OS標準メトリクスから監視を始めるのはアプリケーションが動いているかどうかという重要事項と関連が弱いシグナルから始めることになるため、おすすめしない 2330
    * ただしトラブルシューティングの味方になるので、全システムで自動的に記録しアラートは設定しないくらいが良い
* 8章にはOSのメトリクスや他のよくあるコンポーネントのメトリクスの説明があるので、知りたかったら読むと良い 2330

「実践Scala入門」読んだ

実践Scala入門

実践Scala入門

読んだ。この本は「コンパクトなコップ本」を目指したと最初に書かれているとおり、この本を読めばひとまずScalaを書けるようになるなと思った。これからScalaを始めたくなったらまずはこの本を読んでおけば十分だと思う。

また、「コンパクトなコップ本」だけに留まらず、実践ではよく使うがコップ本ではあまり言及されていないような機能についても解説されていたことが非常に良かった。例えばコップ本ではOptionやEither、Tryなどを使ったエラー処理についてあまり書かれておらず、昔Scalaを始める時にエラー処理のやり方で詰まったことがあった。その時にこの本を読んでいたらもっとスタートダッシュが速かっただろうと思う。他にも実践ではほとんどの場合利用するsbtについても解説されているのも良かった。

こんな感じでScala入門するには最適な一冊だと感じました。

読書ノート

- javaでscalaのコンパイル後jarを動かす方法。scala標準ライブラリにクラスパスが通ってれば良い 20
- scalatestのscaladocは品質が高いらしい、あとで調べる 34
- オプションにnull渡すとnoneになるのでjavaライブラリをラップも出来る 104
- ジェネリックな型をサブタイプにする 109
- :で終わると右結合 130
- updateという関数は、代入で置き換えられる 140
- future周り教えてくれるのがいい。コップ本だとなかった? 158
- print:namer試したい 172
- partialfunctionにはマッチしないかもしれないパターンマッチを渡しても大丈夫 172
- sbtのビルドのスコープにはプロジェクト軸、コンフィグレーション軸、タスク軸があり、それらすべてでキーごとの値を変更可能 200
- sbtの設定できるキーの一覧は https://github.com/sbt/sbt/blob/develop/main/src/main/scala/sbt/Keys.scala で確認可能 204
- privateめそっどのテストに使えるtrait便利そう、ただパッケージプライベートで問題ないらしい 223
- AsyncFunSuite 226
- partial functionでcaseを全部書かなくて済む。isDefinedAtで呼び出しが成功するか確認可能 241
- extends AnyValして値クラスを作るとJVMレベルのオブジェクト生成が可能な限り行われないようになる 244
- メソッドから無名関数への変換処理をη-expansionというのは知らなかった 251

jstatを使うとJVMのメモリ使用状況が分かる

最近頻繁に手元で起動したsbtがjava.lang.OutOfMemoryError: Metaspaceで死ぬので、メモリ使用状況を確認するコマンドを調べた。備忘録として残しておく。

の記事が参考になる。

jpsとjstatを利用する。この二つはJDKに含まれているのでインストールされていれば利用可能。

まずjpsJVMが動いているプロセスを特定する。

$ jps -v
60820 Main
55060 sbt-launch.jar -Xms1024m -Xmx1024m -XX:ReservedCodeCacheSize=128m -XX:MaxMetaspaceSize=256m
76790 Main
1067  -Xms128m -Xmx750m -XX:ReservedCodeCacheSize=240m -XX:+UseCompressedOops -Dfile.encoding=UTF-8 -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50 -ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true -Djdk.http.auth.tunneling.disabledSchemes="" -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -Xverify:none -XX:ErrorFile=/Users/shibayu36/java_error_in_idea_%p.log -XX:HeapDumpPath=/Users/shibayu36/java_error_in_idea.hprof -Djb.vmOptionsFile=/Applications/IntelliJ IDEA CE.app/Contents/bin/idea.vmoptions -Didea.java.redist=jdk-bundled -Didea.home.path=/Applications/IntelliJ IDEA CE.app/Contents -Didea.executable=idea -Didea.platform.prefix=Idea -Didea.paths.selector=IdeaIC2018.3
55853 Jps -Dapplication.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home -Xms8m

今見たいJVMのプロセスが55060 sbt-launch.jar -Xms1024m -Xmx1024m -XX:ReservedCodeCacheSize=128m -XX:MaxMetaspaceSize=256mだとすると、プロセスIDは55060なので次のコマンドでメモリ状況が分かる。-tはタイムスタンプをつけるオプション、-h5は5行ごとにヘッダを出すオプション、最後の1000は1秒ごとに統計情報を出力するオプション。

$ jstat -gc -t -h5 55060 1000
Timestamp        S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
         1054.8 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1055.8 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1056.8 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1057.8 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1058.8 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
Timestamp        S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
         1059.9 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1060.9 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1061.8 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1062.8 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711
         1063.9 76800.0 78336.0 53909.3  0.0   192512.0 179123.1  699392.0   75597.7   106496.0 94784.9 13056.0 12218.8     20    0.296   5      0.415    0.711

この中でMetaspaceのCapacityはMCの106496.0KB、Metaspaceで実際に利用している使用量はMUの94784.9KBとなる。この値がMaxMetaspaceSizeに指定された256MBを超えるとjava.lang.OutOfMemoryError: Metaspaceで死ぬ。


以上、簡単にMetaspaceの利用状況を知る方法でした。