勉強日記

チラ裏

入門監視 ch7 アプリケーション監視

www.oreilly.co.jp


  • アプリケーションの監視が疎かになりがち
    • サーバインフラ、セキュリティ、ネットワークはちゃんと監視するのに
    • アプリケーションこそ最も高頻度で変更されるのに
    • アプリケーションのパフォーマンスに対する可用性の監視は重要
      • 【補】0.1秒読み込みが早いと売上1%増(Amazon調べ)
  • なぜ
    • アプリケーション監視は難しすぎると思われている
    • アプリケーション監視には専門的で高度なスキルセットが必要だと思われている
  • そんなことないよ

メトリクスでアプリケーションを計測する

  • アプリケーション自体の監視をせよ
  • アプリケーションにメトリクスを追加するのは難しい・時間がかかる?
  • まずはシンプルに始めよう
    • DBクエリ発行にかかった時間
    • 外部ベンダのAPIが応答するのにかかった時間
    • 1日に発生したログインの数
  • StatsD使え
    • Graphite + Grafanaとのスタックでよく使われるそう
    • 【補】fluentd + Elasticsearch + Kibanaみたいなかんじ
    • できること
      • 事象の回数を数える
      • 処理時間を測定する(タイマ)

【コラム】APMについて

  • APM: Application Performance Monitoring
  • さまざまな情報を自動で取得する
    • アプリケーションのパフォーマンス
    • スロークエリ
    • アプリケーションの動作のwaterfall chart
  • 【注意】ツールは、ビジネスロジックに関する何のコンテキストも把握していない
    • どこが遅いとまずいのか(クリティカルパス)は教えてくれない
    • アプリケーションが何を行うのかは教えてくれない

(Statsdは)内部ではどのように動いているのか

  • C-S構成
  • Client
    • アプリケーションを計測するコードライブラリ
    • UDPでServerにメトリクスを送信する
  • Server
    • メトリクス受け取る
    • サーバーの各ノードで動かしても、中央StatsDサーバーを立ててもいい
  • UDPという選択
    • 観察者効果の排除
      • アプリケーションパフォーマンスに大きな影響を及ぼさない
    • TCPを使うことはできるが、使う理由はない
  • フラッシュ間隔ごとに、集約されたメトリクスをサーバーに送信する
  • 集約関数はいろいろ
    • 90パーセンタイルの平均(mean)
    • 90パーセンタイルの上限
    • 90パーセンタイルの合計
    • 一定時間の全タイマの上限
    • 一定時間の全タイマの下限
    • 一定時間の全タイマの合計
    • 一定時間の全タイマの平均(mean)
    • 一定時間にタイマが収集した数
  • バックエンドをいろいろ選べる
    • Carbon(Graphite)

      Make it easy to store and graph metrics.

    • OpenTSDB

      A scalable, distributed Time Series Database

    • InfluxDB

      InfluxData provides the leading time series platform to instrument, observe, learn and automate any system, application and business process across a variety of use cases.

    • その他もろもろのSaaSツール

ビルドとリリースのパイプラインの監視

  • ビルドやリリースのパイプラインまたは手順自体の監視
  • 動くか動かないかだけじゃ?
  • それだけじゃない
    • デプロイがいつ始まったか
    • デプロイがいつ終わったか
    • どのビルドがデプロイされたか
    • 誰がデプロイを実行したか
  • アプリケーションやインフラのメトリクスと併用すると有用
  • 例: あるバージョンのデプロイを境にAPIエラー率が上がった
  • Measure Anything, Measure Everything by Etsy
    • StatsDを作った人

healthエンドポイントパターン

  • /healthというエンドポイントを切るやつに著者が名前をつけた
  • ここにHTTPアクセスして、アプリケーションの健全性をチェックする
  • アプリケーションについての基本的な情報を含めたりもする
    • デプロイされたバージョン
    • 依存性のステータス
  • アプリケーションがメトリクスを送りつける(push)のではない。pullベースのやり方
  • 利点
    • ロードバランサやサービスディスカバリシステムによるヘルスチェックにも使用できる
      • 【補】AWS ELBの例
        • pingパスでhealthチェックに使用するエンドポイントを指定できる
        • pingプロトコルpingポートでアクセスして、200OKが返ればhealthy
    • デバッグに有用
      • 環境内が何が動いているかわかる
    • アプリケーション自身が健全性を把握できる
    • 【補】dockerコンテナのプロセス準備完了待ちにも使えますね
      • Compose の起動順番を制御
      • Docker Composeのdepends_onは、プロセスの準備完了を待ってはくれない
      • プロセスの準備完了をポーリングするにあたり、/healthは有用
  • pushベース(メトリクス送信)と二者択一ではない。併用できる
  • 依存のチェックを増やしていくと
    • アプリケーション自身が、自身のhealthを把握するようになる
    • エンドポイントの実装はどんどん複雑になる
      • 問題はいずこ
  • healthエンドポイントはアプリケーションから分けるべき?
    • それじゃ意味ない
    • 監視の仕組みがアプリケーションと一緒に提供されるよう、アプリケーション内に
  • ちゃんと200 OKとか503 Service Temporarily Unavailableとか使え
    • レスポンスをパースしなくても正常動作か否かわかる
    • シンプルならステータスコードだけでいい
  • セキュリティの懸念
    • ユーザがアクセスできるとまずい
      • DBMSがバレちゃうとか
    • 特定のソースアドレスのみアクセスできるようにすると良い
      • 他はリダイレクト
  • デメリット
    • シンプルなpushベースよりもエンジニアリング作業が多くかかる
      • エンドポイントの実装
      • エンドポイントをポーリングする仕組みの用意

アプリケーションロギング

  • 構造化ログ使え
    • せいぜいgrepやtailを使って人間が読むだけなら非構造化ログでもいい
    • 自動的に集約してあれこれするなら必須
      • fluentdとかで
    • JSONとか

メトリクスにすべきか、ログにすべきか

  • 著者の経験則
    • チームにとってメトリクスで考えるほうが楽か、ログで考えるほうが楽か
    • ユースケースに照らして、どちらがより効果的か
  • 情報量的にはログのほうがずっと有益
    • ログからメトリクス作れる
      • 単にツールの問題で世間一般ではそこに至っていない

何のログを取るべきか

  • 全部取りたいが…
    • ネットワークやディスクを飽和させる
    • アプリケーションのパフォーマンス劣化
  • ログレベル
    • 便利だが使うのは存外難しい
  • トラブルシューティングや、仕組みの説明の際にあったら便利な情報を取ろう
  • 【補】きのこ85 -- 冗長なログは眠りを妨げる

    ログに、不要なものも含め、あまりに多くの情報が記録されると、システムの監視には役立たなくなってしまいます。本当に重大な問題が起きた場合以外、基本的にエラーログには何も記録されない、というくらいの方が良いと言えます。その場合は、エラーログにメッセージがあるというだけで、システムに重大な問題が発生しているとすぐ判断できるからです。

ディスクに書くべきか、ネットワーク越しに送るべきか

  • まずディスクに書く
  • 定期的に外部に送る
  • 最初からネットワークに送りつけるのはよくない
    • ログエントリを送るたびにネットワークコネクションを張ることになり、パフォーマンス劣化

サーバレスまたはFunction-as-a-Service

  • AWS LambdaとかGoogle Cloud Functionsとか
  • クラウドプラットフォームがいろいろ記録してくれる
    • 実行時間
    • 呼び出し回数
    • エラー率
  • Functionの中で何が起きたか知りたい場合は?
    • 処理中(1秒とか)しか動いていないので、伝統的なポーリングは使えない
    • StatsDを使おう
      • 【補】Functionの中でStatsDコードライブラリを利用し、StatsDサーバーにメトリクスを送りつける
  • Functionから利用するサービスにもログやメトリクスが備わっていることを忘れずに

マイクロサービスアーキテクチャを監視する

  • どこからリクエストが始まり、どこへ到達し、何が問題になる可能性があるか
  • モノリシックなサービスは理解しやすい
    • 多少水平スケールしてもどうってことない
  • マイクロサービスは複雑
  • 分散トレーシング(distributed tracing)
    • リクエストにIDを付与し、追跡する
    • どのサービスでどれくらいレイテンシがあったかわかる
    • 個々のリクエストに焦点を当てるのが特徴
      • cf. メトリクスは、リクエストの集合に対して何らかの値を集約したもの
  • 必要な現場は限られている
    • まずはメトリクスとログ。これで済むなら一番手っ取り早い
    • それでも分散システムにおけるサービス間のパフォーマンスを把握したりトラブルシューティングするのに困るなら導入
    • 大掛かりなサーバレスインフラがある場合も

まとめ

  • メトリクスとログでアプリケーションを計測するのは、アプリケーションのパフォーマンスを把握し、トラブルシューティングする能力を高めるためにできる最も重要なこと
  • アプリケーションやインフラのリリースやパフォーマンスに関係することを追跡しよう
  • 役立つアーキテクチャが限られているとはいえ、/healthエンドポイントパターンはなかなかよい方法
  • 相当大規模にデプロイしているのでない限り、サーバレスまたはマイクロサービスの監視は、他のアプリケーションと大きく違いはない。分散トレーシングを始めるには、時間と労力がかかるだろう

次章、サーバインフラの監視