- AWS X-Ray について
— AWS X-Ray とは何ですか?
— AWS X-Ray が出来ること
— 概念
— AWS X-Ray の画面
—– Service Map
—– Traces
—– Trace の詳細
— AWS X-Ray を利用する方法
—– X-Ray SDK
—– X-Ray デーモン
—– X-Ray API
—– AWS CLI - ローカル環境でチュートリアル
— 環境
— X-Ray デーモンの用意
—– X-Ray デーモンのインストール
—– X-Ray デーモン設定ファイルの作成
—– アクセスキー、シークレットアクセスキーを用意
—– X-Ray デーモンの起動
— アプリケーションの用意
—– Node.js と Express の用意
—– AWS SDK for JavaScript と X-Ray SDK の導入
—– app.js
—– /set
—– /get
— アプリケーションを実行して計測してみる
—– アプリケーションの起動
—– アプリケーションへの断続的なアクセス
—– Service Map
—– Traces
—– Trace の詳細 - ということで…
— フィルタ についても
— X-Ray デーモンを使えば
— X-Ray8 SDK 待ち
AWS X-Ray について
AWS X-Ray とは何ですか?
上記の資料が簡潔に纏まっていてとても参考になった。
そして、FAQ の記述を引用すると…
開発者は、AWS X-Ray を使用して、本番環境や分散アプリケーション (マイクロサービスアーキテクチャを使用して構築されたアプリケーションなど) を分析およびデバッグできます。X-Ray を使用すると、アプリケーションやその基盤となるサービスの実行状況を把握し、パフォーマンスの問題やエラーの根本原因を特定して、トラブルシューティングを行えます。X-Ray では、アプリケーション内で転送されるリクエストがエンドツーエンドで表示され、アプリケーションの基盤となるコンポーネントのマップも表示されます。X-Ray を使用すると、開発中か本番環境かにかかわらず、シンプルな 3 層アプリケーションから数千のサービスで構成される複雑なマイクロサービスアプリケーションまで、さまざまなアプリケーションを分析できます。
ざっくり言うと…アプリケーションのモニタリングサービスで、競合は NewRelic や Datadog APM になると思う。
AWS X-Ray が出来ること
こちら より転載。
- パフォーマンスボトルネックとエラーの特定
- アプリケーション内の特定サービスへの問題を特定
- アプリケーションのユーザに対する問題のインパクトを特定
- アプリケーションのサービスコールグラフの可視化
概念
docs.aws.amazon.com
こちら より転載。
キーワード | 内容 |
---|---|
Trace | サービスをまたがった単⼀リクエストに関連したエンドツーエンドのデータ |
Segments | 1 つのサービスに対応するトレースの⼀部 |
Sub-segments | サービス内でのリモートコールもしくはローカルコンピュートのセクション |
Annotations | トレースをフィルタするのに使⽤できるビジネスデータ |
Metadata | トレースに対して付与できるビジネスデータ ただし、トレースのフィルタリングには使⽤されない |
Errors | 正規化されたエラーメッセージとスタックトレース |
Sampling | トレースとして取得するアプリケーションへのリエストの割合 |
AWS X-Ray の画面
Service Map
Service Map とはトレースデータを視覚化したもの。
各ノード(上図だと緑色◯)をクリックするとトレースデータを確認する事が出来る。
Traces
トレース画面ではアプリケーションへのリクエストのレイテンシやステータスコードを確認する事が出来る。
アプリケーションへのトレースデータには ID が付与されていて、トレース ID をクリックするとトレースの詳細を確認する事が出来る。
Trace の詳細
Trace の詳細画面ではアプリケーションのリクエスト開始から終了までの個々の処理が 1 つのセグメントとして詳細を確認する事が出来る。
例えば、上図だと MyApp
や DynamoDB
はそれぞれ別のセグメントとして認識され、アクセスしたリソースや例外が発生した場合等は例外の情報まで確認する事が出来る。
AWS X-Ray を利用する方法
X-Ray SDK
- Java、.NET、Node.js で利用可能
- 主要なアプリケーション呼び出し対するメタデータを自動的にキャプチャするフィルタを標準で用意
X-Ray デーモン
- SDK から UDP でデータを受信し、ローカルバッファとして振る舞う
- データは毎秒でバックエンドに送信し、ローカルバッファが一杯になるとフラッシュされる
- Amazon Linux や RHEL 、Ubuntu や OS X 及び Windows で利用可能
X-Ray API
X-Ray SDK がサポートしていない言語からも X-Ray API を利用してトレースデータを送信することは出来、以下のような API が提供されている。こちらより抜粋。
API | 用途 |
---|---|
PutTraceSegments | AWS X-Rayへセグメントのドキュメントをアップロード |
BatchGetTraces | IDにより指定されたトレースのリストを検索 |
GetServiceGraph | アプリケーションとコネクション内でサービスを⽰すドキュメントを検索 |
GetTraceSummaries | オプションのフィルタを使⽤して、指定された時間 枠で使⽤可能なトレースのIDとメタデータを取得 |
AWS CLI
ローカル環境でチュートリアル
環境
以下のような環境でチュートリアルする。
$ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=16.04 DISTRIB_CODENAME=xenial DISTRIB_DESCRIPTION="Ubuntu 16.04.2 LTS" $ xray --version AWS X-Ray daemon version: 1.0.1 $ node --version v7.10.0 $ java -version openjdk version "1.8.0_121" OpenJDK Runtime Environment (build 1.8.0_121-8u121-b13-0ubuntu1.16.04.2-b13) OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode) $ ps aux | grep DynamoDB ubuntu 6193 0.4 12.2 2658392 124676 pts/1 Sl 05:31 1:03 java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb
xray デーモンが動けば EC2 や ECS 上のコンテナである必要が無いのは嬉しい限り。
そして、Node.js アプリケーションは express を利用して、DynamoDB Local テーブルにデータを登録したり、登録データを取得する雑なアプリケーションを利用する。(見よう見真似で作ってみた)
X-Ray デーモンの用意
X-Ray デーモンのインストール
X-Ray デーモンのパッケージを取得して dpkg
コマンドでインストールする。
$ wget https://s3.amazonaws.com/aws-xray-assets.us-east-1/xray-daemon/aws-xray-daemon-1.x.deb $ sudo dpkg -i aws-xray-daemon-1.x.deb
インストール後、--help
オプションでヘルプ一覧を確認。
$ xray --help Usage: X-Ray [options] -m --memory-limit Change the amount of memory (in MB) that the daemon can use. -o --local-mode Don\'t check for EC2 instance metadata. -b --bind Overrides default UDP address (127.0.0.1:2000). -r --role-arn Assume the specified IAM role to upload segments to a different account. -c --config Load a configuration file from the specified path. -f --log-file Output logs to the specified file path. -l --log-level Log level, from most verbose to least: dev, debug, info, warn, error, prod (default). -v --version Show AWS X-Ray daemon version. -h --help Show this screen
X-Ray デーモン設定ファイルの作成
X-Ray 用の設定ファイルを以下のように作成する。(ファイル名は任意の名前で構わない)
Processor: Region: "ap-northeast-1" Logging: LogLevel: "warn" LogPath: "/tmp/xray-daemon.log" LocalMode: true
ローカル環境で動かす場合、LocalMode
は true
にしておく必要がある。尚、false
の場合、EC2 メタデータから情報を取得しようとする。
アクセスキー、シークレットアクセスキーを用意
マネージドポリシーの AWSXrayWriteOnlyAccess
が付与された IAM User のアクセスキー、シークレットアクセスキーを用意する。
$ cat ~/.aws/credentials [default] aws_access_key_id = AKxxxxxxxxxxxxxxxxxxxxx aws_secret_access_key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx region = ap-northeast-1
X-Ray デーモンの起動
以下のように設定ファイルを指定して X-Ray デーモンを起動する。
$ xray --config /path/to/xray-daemon.yaml & $ ps aux | grep xray ubuntu 6216 0.0 1.8 230788 18848 pts/1 Sl 05:31 0:05 xray --config /vagrant/xray/xray-daemon.yaml
アプリケーションの用意
Node.js と Express の用意
こちら の記事を参考にさせて頂いて、Node.js と Express を用意した。
$ tree -L 1 sampleapp sampleapp ├── app.js ├── bin ├── node_modules ├── package.json ├── public ├── routes └── views 5 directories, 2 files
AWS SDK for JavaScript と X-Ray SDK の導入
以下のように AWS SDK for JavaScript と X-Ray SDK の導入。
$ cd sampleapp $ npm install aws-sdk --save --no-bin-links $ npm install aws-xray-sdk --save --no-bin-links
今回、Vagrant の共有ディレクトリにアプリケーションプロジェクトのディレクトリを作成した為、--no-bin-links
オプションを付けてインストールした。
$ cat sampleapp/package.json { "name": "sampleapp", "version": "0.0.0", "private": true, "scripts": { "start": "node ./bin/www" }, "dependencies": { "aws-sdk": "^2.49.0", "aws-xray-sdk": "^1.1.0", "body-parser": "~1.17.1", "cookie-parser": "~1.4.3", "debug": "~2.6.3", "express": "~4.15.2", "jade": "~1.11.0", "morgan": "~1.8.1", "serve-favicon": "~2.4.2" } }
app.js
以下のような修正を加えた。
$ diff -u app.js.original app.js --- app.js.original 2017-05-07 10:01:23.000000000 +0000 +++ app.js 2017-05-07 06:15:55.000000000 +0000 @@ -7,9 +7,15 @@ var index = require('./routes/index'); var users = require('./routes/users'); +var ddb_set = require('./routes/set'); +var ddb_get = require('./routes/get'); var app = express(); +// for aws-xray +var AWSXRay = require('aws-xray-sdk'); +app.use(AWSXRay.express.openSegment('MyApp')); + // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); @@ -24,6 +30,11 @@ app.use('/', index); app.use('/users', users); +app.use('/set', ddb_set); +app.use('/get', ddb_get); + +// for aws-xray +app.use(AWSXRay.express.closeSegment()); // catch 404 and forward to error handler app.use(function(req, res, next) {
以下を設定することで、Express アプリケーションが提供する受信 HTTP リクエストをトレースする事が出来るようになる。
var AWSXRay = require('aws-xray-sdk'); app.use(AWSXRay.express.openSegment('MyApp')); ... app.use('/', index); app.use('/users', users); app.use('/set', ddb_set); app.use('/get', ddb_get); ... app.use(AWSXRay.express.closeSegment());
MyApp
がアプリケーション名として X-Ray ダッシュボードの Service Map でも確認する事が出来る。
尚、/set
が DynamoDB に値をセットし、/get
で DynamoDB のテーブルを Scan して結果を返すようにしてみた。
/set
本当に見よう見真似の書き方でだいぶん怪しいが、/set
にアクセスすると以下の処理が実行される。
var express = require('express'); var router = express.Router(); var AWSXRay = require('aws-xray-sdk'); var AWS = AWSXRay.captureAWS(require('aws-sdk')); var dynamodb = AWSXRay.captureAWSClient(new AWS.DynamoDB({ endpoint: new AWS.Endpoint('http://localhost:8000'), region: 'ap-northeast-1' })); router.get('/:key', function(req, res) { var params = { TableName: 'SampleTable', Item: { 'Artist': {"S": req.params.key}, 'SongTitle': {"S": req.params.key} } }; dynamodb.putItem(params, function (err, data) { if (err) { console.log(err, err.stack); } else { console.log(req.params.key); res.render('ddb_set', { message: "OK" }); } }); }); module.exports = router;
以下のように記述して AWS SDK を利用した DynamoDB への呼び出しを AWSXRay.captureAWSClient
でラップすることで、DynamoDB を呼び出す処理についてもトレースする。
var AWSXRay = require('aws-xray-sdk'); var AWS = AWSXRay.captureAWS(require('aws-sdk')); var dynamodb = AWSXRay.captureAWSClient(new AWS.DynamoDB({ endpoint: new AWS.Endpoint('http://localhost:8000'), region: 'ap-northeast-1' }));
DynamoDB Local を利用しているので endpoint
は http://localhost:8000
を指定している。
/get
/set
同様にだいぶん怪しいが、/get
にアクセスすると以下の処理が実行される。
var express = require('express'); var router = express.Router(); var AWSXRay = require('aws-xray-sdk'); var AWS = AWSXRay.captureAWS(require('aws-sdk')); var dynamodb = AWSXRay.captureAWSClient(new AWS.DynamoDB({ endpoint: new AWS.Endpoint('http://localhost:8000'), region: 'ap-northeast-1' })); router.get('/', function(req, res) { dynamodb.scan({TableName: "SampleTable", Select: "ALL_ATTRIBUTES", }, function (err, datas) { console.log(JSON.stringify(datas)); res.render('ddb_get', { datas: datas }); }); }); module.exports = router;
/set
と同様の設定で DynamoDB への呼び出しをトレースするようにする。
アプリケーションを実行して計測してみる
アプリケーションの起動
以下のようにアプリケーションを起動する。
node bin/www &
アプリケーションへの断続的なアクセス
以下のように実行してアプリケーションへ断続的にアクセスさせる。
while true; do curl -s localhost:3000/set/$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1 | sort | uniq); sleep 15; curl -s localhost:3000/get; sleep 15; done
暫く動かしつつ X-Ray のダッシュボードを確認すると…
Service Map
以下のように出力されている。
なかなかカッコイイ。
Traces
Trace の詳細
セグメントをクリックすると…
ということで…
フィルタについても
書きたいと思っている。
X-Ray デーモンを使えば
AWS 以外で動いているアプリケーションもトレースする事が出来るのは嬉しい。
X-Ray SDK 待ち
X-Ray SDK に対応している言語が少ないのが残念(Datadog APM は Python と Ruby と Go をサポートしている)だけど、Datadog APM や NewRelic のようなアプリケーションのパフォーマンスの計測が AWS だけで行えるというのも嬉しい。(※ AWS SDK や AWS CLI でトレースデータを送信や取得は出来る)
元記事はこちら
「ゴールデンウィークスペシャル:AWS X-Ray を出来るだけローカル環境でチュートリアルする(Node.js + Express + DynamoDB Local を使って)」