LoginSignup
3
0

More than 3 years have passed since last update.

AWS X-RayをJavaバッチ処理に適用したい

Posted at
1 / 19

AWS X-Rayとは


X-Rayの特徴

  • managed service
  • 従量料金(永久無料枠あり)
  • agent(デーモン) はトレース情報の送信のみ
  • トレース情報を作るのはApplicationに埋め込むSDK
    • ソース修正・ビルドが必要

X-Rayの使いどころ

  • 商用APMのライセンス体系の隙間
    • マイクロサービス(有償agentフィーが…)
    • Serverless(agent入れようがない)
    • 多数のバッチ処理
    • 開発環境(開発初期こそAPMが欲しい → 無料枠で)

Javaバッチに適用

  • SampleはほとんどWeb Application
  • HTTP Requestをトレースするのは SDK入れてimport文を差し替えるだけ

この本筋の紹介ばかりが目立って、ググってもバッチ適用例に当たらないが…

非同期のシンプルなイベント呼び出し、3 層のウェブアプリケーション、数千のサービスで構成される複雑なマイクロサービスアプリケーションなど

「非同期のシンプルなイベント呼び出し」できると書いてある → やってみよ


見事な空振り

SDK入れるだけで、AWS API CALLはトレースされるって?
なにかAWSコンソールで見えるようになるかも?

  1. 既存Javaバッチ処理に xray SDK 依存関係追加(Maven pom.xml)
  2. ビルド・開発デプロイ
  3. job実行

なにも起きなかった


X-Ray デーモン

  • UDP ポート 2000 のトラフィックをリッスン
  • AWS X-Ray API に中継する
# curl .../xray-daemon/aws-xray-daemon-2.x.rpm -o xray.rpm
# yum install -y xray.rpm 

AWS X-Rayコンソールはピクリとも動かない


デーモンログ

# ps ax | grep xray
13910 ?        Ssl    0:01 xray -f /var/log/xray/xray.log
# cat /var/log/xray/xray.log
2019-07-09T17:13:11+09:00 [Info] Initializing AWS X-Ray daemon 2.1.3
2019-07-09T17:13:11+09:00 [Info] Using buffer memory limit of 78 MB
2019-07-09T17:13:11+09:00 [Info] 1248 segment buffers allocated
2019-07-09T17:13:11+09:00 [Info] Using region: ap-northeast-1

デーモンは正常そうだ。port 2000に何も来てないっぽい。


X-RayのHello World

# sh xray_start.sh
# tail /var/log/xray/xray.log
019-07-10T11:01:11+09:00 [Error] Sending segment batch failed with: AccessDeniedException: 
User: arn:aws:sts::...:assumed-role/...-role/i-... 
is not authorized to perform: xray:PutTraceSegments

AWS Ops のあるある 「Sigh. また権限追加か…」
追加後、X-Rayコンソールの Traces に1個出た!


TraceIdとは

SDKの中で生成したり、SQSにもうTraceIDが入っているところから始まるsampleばかりで、どこで誰がどう作るのか???
xray_start.sh 読む

START_TIME=$(date +%s)
HEX_TIME=$(printf '%x\n' $START_TIME)
GUID=$(dd if=/dev/random bs=12 count=1 2>/dev/null | od -An -tx1 | tr -d ' \t\n')
TRACE_ID="1-$HEX_TIME-$GUID"

"1-" + Epoch Time の Hex表現 + "-" + GUID
どこの誰でも生成できるID体系:ユニーク性と概ね時系列が要件っぽい


Javaバッチに追記

import com.amazonaws.xray.AWSXRayRecorder;
import com.amazonaws.xray.AWSXRayRecorderBuilder;
import com.amazonaws.xray.entities.TraceID;
import com.amazonaws.xray.plugins.EC2Plugin;
...
    private static AWSXRayRecorder xRayRecorder = AWSXRayRecorderBuilder.standard().withPlugin(new EC2Plugin()).build();
    private static final TraceID traceId = new TraceID();
...
        xRayRecorder.beginSegment(traceId.toString());
...
        xRayRecorder.endSegment();
...

参考sample: https://github.com/aws-samples/aws-xray-apache-kafka-sample


Java追記まとめ

  1. import追加して
  2. AWSXRayRecorderを build して
  3. TraceID 生成して
  4. 処理を AWSXRayRecorder.beginSegment(), endSegment() でくくる

出たぞ

[root@gin-mng-za-1 ~]# tail /var/log/xray/xray.log
...
2019-07-11T09:26:29+09:00 [Info] Successfully sent batch of 1 segments (0.086 seconds)
{
    "Duration": 42.792,
    "Id": "1-5d26820a-5249372acaaa8b1b875a72e5",
    "Segments": [
        {
            "Document": {
                "id": "6626990748dee123",
                "name": "1-5d26820a-83c2abc49e5ca6595e9f9dbd",
                "start_time": 1562804746.446,
                "end_time": 1562804789.238,
                "aws": {
                    "ec2": {
                        "availability_zone": "ap-northeast-1a",
                        "instance_id": "i-..."
                    },
                    "xray": {
                        "sdk_version": "2.2.0",
                        "sdk": "X-Ray for Java"
                    }
                },
                "service": {
                    "runtime": "Java HotSpot(TM) 64-Bit Server VM",
                    "runtime_version": "1.8.0_..."
                },
                "trace_id": "1-5d26820a-5249372acaaa8b1b875a72e5",
                "origin": "AWS::EC2::Instance"
            },
            "Id": "6626990748dee123"
        }
    ]
}

JDBCInterceptor

xray SDKを依存ライブラリに入れてあれば jdbc.properties に 1行追記だけ

dataSource.jdbcInterceptors=com.amazonaws.xray.sql.postgres.TracingInterceptor

subsegments がいっしょに PUTされた

"subsegments": [
                    {
                        "id": "23894958bbe2a6a0",
                        "name": "s....@db.....rds",
                        "start_time": 1562824789.49,
                        "end_time": 1562824789.532,
                        "sql": {
                            "url": "jdbc:postgresql://db....rds:.../s...",
                            "database_type": "PostgreSQL",
                            "database_version": "9.....",
                            "driver_version": "...",
                            "user": "...",
                            "preparation": "statement"
                        },
                        "namespace": "remote"
                    }
                ]

HTTP Service 呼出

Apache HttpClient を com.amazonaws.xray.proxies の互換classにソース上で差し替える

import 文置き換えだけでロジックそのままで済むんじゃないかな

import com.amazonaws.xray.proxies.apache.http.HttpClientBuilder;
...
CloseableHttpClient httpclient = HttpClientBuilder.create().build();  //変更なし

これだけで、HttpClient経由のAPIが subsegments として追加される(はず)


ソース変更まとめ

  1. pom.xml に xray SDK追加して
  2. main の import追加して
  3. AWSXRayRecorderを build して
  4. TraceID 生成して
  5. 処理を AWSXRayRecorder.beginSegment(), endSegment() でくくる
  6. jdbc.properties に interceptor 設定追加する
  7. HttpClientの import文を xray SDK の class に差し替える

インフラ変更まとめ

  1. 対象instance に xray デーモンをインストール
  2. 対象instance profile に xray:PutTraceSegments などを許可
    • 参考:AWS管理ポリシー AWSXRayDaemonWriteAccess

コスト試算

  • 5分, 10分, 15分, 30分周期の job各1本
  • その他1日1回のjob数本
  • 合計 585 jobs/day = 18K/mo
  • X-Rayの永久無料枠は 100K/mo ずっと無料

※クエリ側料金もあるけどアドホック検索してるうちは無料枠内でしょう


残件

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0