アプリケーションやシステムの性能管理・監視、いわゆる、アプリケーションパフォーマンス管理として、APMツールを導入しているプロジェクトは多いと思います。最近では、よくDatadogや、NewRelicなどを導入している記事をよく見かけますが、今回は、アプリケーションのパフォーマンス管理のために、Amazon ECSで動かしているRailsアプリケーションにAWS X-Rayを導入したことについて書きます。
AWS X-Rayとは
概要は以下を参照。
https://docs.aws.amazon.com/ja_jp/xray/latest/devguide/aws-xray.html
料金
料金については、こちらに全て書かれているが、要約すると、
-
デフォルトでかかる料金
- トレースの記録数による従量課金
- トレースの取得数による従量課金
- トレースのスキャン数による従量課金
-
トレースの記録数
- リクエスト単位で、記録しているトレース数のこと
-
トレースの取得数
- クエリで検索して取得したトレース数のこと
-
スキャン数
- クエリでの検索のためスキャンしたトレース数のこと
-
料金例: 公式から抜粋
料金の例
1 時間あたり 2,000 件の受信リクエストを受け取るアプリケーションを使用していて 10% のサンプリングの頻度を使用している場合、料金は以下のように計算されます。
記録されたトレース
1 か月あたりのトレース記録件数 = 1 時間あたり 2,000 リクエスト x 24 時間 x 31 日 x 10% = 148,800 トレース
1 か月あたりの有料トレース記録件数 = 148,800 トレース – 無料利用枠の 100,000 トレース = 48,800 トレース
トレース記録の月額料金 = 48,800 トレース * 0.000005 USD = 0.24 USD
さらに、1 日あたり 100 回のクエリを実行し、各クエリでは直近 1 時間のキャプチャされたデータ (200 トレース) をスキャンし、クエリ 1 回につき 50 件のトレースのフルトレースデータを取得すると仮定します。
取得およびスキャンされたトレース
1 か月あたりのトレースのスキャン件数 = 100 クエリ x 1 時間あたり 200 トレース x 31 日 = 620,000 トレース
1 か月あたりのトレースの取得件数 = 100 クエリ x 1 クエリあたり 50 トレース x 31 日 = 155,000 トレース
1 か月あたりのトレースの取得/スキャンの合計件数 = 155,000 トレース + 620,000 トレース = 775,000 トレース
1 か月あたりの有料でのトレースの取得/スキャン件数 = 775,000 トレース – 無料利用枠の 1,000,000 トレース = 0 トレース
トレースの取得とスキャンの月額料金 = 0 トレース * 0.0000005 USD = 0 USD
加えて、一部またはすべての X-Ray グループで X-Ray Insights を有効にしているとしましょう。
処理された X-Ray Insights トレース
1 か月あたりのトレース記録件数 = 1 時間あたり 2,000 リクエスト x 24 時間 x 31 日 x 10% = 148,800 トレース
1 か月あたりの処理された Insights トレース変更件数 = 148,800 トレース * 0.000001 USD = 0.15 USD
AWS X-Ray の月額利用料金は 0.24 USD + 0.15 USD = 合計 0.39 USD となります
手順
アプリ側の設定
-
基本はこのREADME通り
-
gem
gem 'aws-xray-sdk', require: ['aws-xray-sdk/facets/rails/railtie']
gem 'oj', platform: :mri
gem 'jrjackson', platform: :jruby
- initializersの設定
Rails.application.config.xray = {
# default segment name generated by XRay middleware
name: "アプリ名-#{ENV.fetch('RAILS_ENV')}", # ←ノード名(x-ray上のサーバー名になるので環境毎に命名を分けてダッシュボードで絞る)
patch: %I[net_http aws_sdk],
# record db transactions as subsegments
active_record: true,
context_missing: 'LOG_ERROR'
}
ECSの設定
-
基本はこの公式通り
-
https://docs.aws.amazon.com/xray/latest/devguide/xray-daemon-ecs.html
-
コンソールにも大体のやり方の紹介は出ている(Rubyアプリケーションの事例はないのでここからは作れない)
-
-
タスク定義に以下の設定のコンテナを追加
- cpuの値はもう少し小さくても良さそう
{
"name": "xray-daemon",
"image": "amazon/aws-xray-daemon",
"cpu": 32,
"memoryReservation": 256,
"portMappings": [
{
"containerPort": 2000,
"hostPort": 2000,
"protocol": "udp"
}
],
"essential": true,
"environment": [],
"mountPoints": [],
"volumesFrom": []
}
- タスクロールにX-Rayを動かすための権限を追加
- ECSにX-Rayの実行権限を追加しないとデータが取れない
- サービスの更新をして反映
- X-Rayデーモンをコンテナで動かした状態で、アプリケーションに何かしらのリクエストを送ると、トレースがスタートし、サービスマップなどが自動で生成される
標準としての設定はこれで完成!!
インサイト(有料)
X-Ray Insights はアプリケーションパフォーマンスの異常を自動的に検出します。しきい値を手動で設定したり、X-Ray で計測するためにアプリケーションを変更したりする必要はありません。
- 料金はかかるため費用インパクトが出てきたら無効にする(すぐに無効にできる)
その他追加設定
サンプリングルール
以下、公式のサマリ。
-
サンプリングルールをカスタマイズすることで、記録するデータの量を制御できる
-
デフォルトルールは、1 秒ごとに最初のリクエストを記録し、それ以降のリクエストは 5% ずつ記録
-
サービスがリクエストを処理している限り、毎秒少なくとも 1 つのトレースが記録され、5% は、リザーバサイズを超えて追加リクエストがサンプリングされるレート
-
サンプリングルールの追加
-
Rails でのレコーダー設定をしていればコンソールで作成したサンプリングルールが設定される
- 環境毎にルールの適用を変えたい場合は環境のhost名ごとにサンプリングルールを作成するなどして出し分けできるように考える
- とりあえずは全環境共通でデフォルトのサンプリングルールでも大きな問題はなさそう
-
デフォルトルールよりも絞る場合は、リザーバーのサイズを0にして、固定レートをたとえば30%とかにすればだいたい全リクエストの30%のみトレースするという感じにできそうで実際トレースもできていた(もし費用を安くしたいなどがあれば)
サービスマップ/トレース
- ノード名にはRailsアプリで設定した命名で設定されRailsアプリへのリクエストのパフォーマンスのデータが表示される
- Railsアプリから派生して、databaseや、AmazonSNSなどのAWSリソースへのアクセス、別のhostの外部APIへのアクセスなども全てトレースされる
- https://docs.aws.amazon.com/ja_jp/xray/latest/devguide/xray-console-servicemap.html
-
グループによるサービスマップのフィルタリング
-
トレースの検索
環境変数
用意された環境変数を使うとX-Ray SDK for Ruby で書いているアプリの設定ソースコードの値を上書きできる。
-
AWS_XRAY_TRACING_NAME
- SDK がセグメントに使用するサービス名を設定。セグメントはノードの名前のこと
-
AWS_XRAY_DAEMON_ADDRESS
- X-Ray デーモンリスナーのホストとポートを設定。デフォルトでは、SDK は、127.0.0.1:2000にトレースデータを送信。別のポートでリッスン、または別のホストで実行されている場合に設定するので、今回は特に上書きする必要なし。
-
AWS_XRAY_CONTEXT_MISSING
- 実装されたコードについてセグメントが開いていないときにデータを記録しようとした場合に例外のスローを回避するために設定
- LOG_ERROR
- エラーを記録して続行
- LOG_ERROR
- 実装されたコードについてセグメントが開いていないときにデータを記録しようとした場合に例外のスローを回避するために設定