Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Java Agent経由で簡単に混沌を注入しよう

Java Agent経由で簡単に混沌を注入しよう

JJUG CCC 2024 Fall 登壇資料:

マルチスレッド、分散システム、複数DB。これらを用いた開発では、本番環境特有の負荷により発生する遅延や例外を通常のテストで再現することは簡単ではありません。本セッションでは「アプリケーションのコード変更をせずにJava Agent経由で混沌 (ランダムな遅延や例外) を注入し、テストで問題を検出しやすくする手法について説明します。

Mitsunori Komatsu

October 31, 2024
Tweet

More Decks by Mitsunori Komatsu

Other Decks in Programming

Transcript

  1. Who am I - Mitsunori Komatsu @Scalar, Inc. - GitHub:

    komamitsu - msgpack-java - jackson-dataformat-msgpack - Fluency (Data ingestion logger to Fluentd) - Chaos Dukey
  2. 人類には早すぎるものたち - マルチスレッド - 分散システム - 複数DB - マイクロサービス :

    テストされなかった処理順序の 組み合わせが本番環境で 突然発生し障害につながる …
  3. 例: Lease-based job queue Producer 1 Producer 2 Producer 3

    Job A Job C Job B Job A Job B Job C Consumer 1 Consumer 2 Dequeue Producer 1 Producer 2 Producer 3 Job A Job C Job B Job A Job B Job C Consumer 1 Consumer 2 Dequeue Job A Job AはConsumer 1に 渡されたので一定時間 他のConsumerには視えない Queue Queue Consumer 1が失敗しても Lease失効後、別の ConsumerがDequeueできる
  4. 例: Lease-based job queue (正常系) Worker 1 Distributed Queue Dequeue

    a job Account DB Job X - Incr Account A by $50 Worker 2 Account A: $200 00:01:30 No Jobs Dequeue a job Account A: $250 Job X が一度のみ 実行されたので 期待通り $250 Job X - Account A に $50 追加 - Owner は Worker 1 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Leaseは 00:01:30 に失効 Increment Account A by $50 Finish Job X No available job Account A: $250
  5. 例: Lease-based job queue (正常系) Worker 1 Distributed Queue Dequeue

    a job Account DB Job X - Incr Account A by $50 Worker 2 Account A: $200 00:01:30 No Jobs Dequeue a job Account A: $250 Job X が一度のみ 実行されたので 期待通り $250 Job X - Account A に $50 追加 - Owner は Worker 1 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Leaseは 00:01:30 に失効 Increment Account A by $50 Finish Job X No available job Account A: $250
  6. 例: Lease-based job queue (正常系) Worker 1 Distributed Queue Dequeue

    a job Account DB Job X - Incr Account A by $50 Worker 2 Account A: $200 00:01:30 No Jobs Dequeue a job Account A: $250 Job X が一度のみ 実行されたので 期待通り $250 Job X - Account A に $50 追加 - Owner は Worker 1 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Leaseは 00:01:30 に失効 Increment Account A by $50 Finish Job X No available job Account A: $250
  7. 例: Lease-based job queue (正常系) Worker 1 Distributed Queue Dequeue

    a job Account DB Job X - Incr Account A by $50 Worker 2 Account A: $200 00:01:30 No Jobs Dequeue a job Account A: $250 Job X が一度のみ 実行されたので 期待通り $250 Job X - Account A に $50 追加 - Owner は Worker 1 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Leaseは 00:01:30 に失効 Increment Account A by $50 Finish Job X No available job Account A: $250
  8. 例: Lease-based job queue (stuck & lease失効) Worker 1 Distributed

    Queue Dequeue a job Account DB Job X - Incr Account A by $50 Worker 2 Increment Account A by $50 Account A: $200 00:01:30 Job Xのleaseが失効 Job X - Incr Account A by $50 Dequeue a job Increment Account A by $50 Account A: $250 Account A: $300 00:02:00 Job X - Account A に $50 追加 - Owner は Worker 1 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Owner は Worker 2 - Lease は 00:02:00 に失効 Job X - Account A に $50 追加 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Lease は 00:02:00 に失効 何らかの理由 (e.g., GC)により 処理が停止・遅延 Finish Job X Finish Job X 二重追加が 本番環境で発生 ...!
  9. 例: Lease-based job queue (stuck & lease失効) Worker 1 Distributed

    Queue Dequeue a job Account DB Job X - Incr Account A by $50 Worker 2 Increment Account A by $50 Account A: $200 00:01:30 Job Xのleaseが失効 Job X - Incr Account A by $50 Dequeue a job Increment Account A by $50 Account A: $250 Account A: $300 00:02:00 Job X - Account A に $50 追加 - Owner は Worker 1 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Owner は Worker 2 - Lease は 00:02:00 に失効 Job X - Account A に $50 追加 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Lease は 00:02:00 に失効 何らかの理由 (e.g., GC)により 処理が停止・遅延 Finish Job X Finish Job X 二重追加が 本番環境で発生 ...!
  10. 例: Lease-based job queue (stuck & lease失効) Worker 1 Distributed

    Queue Dequeue a job Account DB Job X - Incr Account A by $50 Worker 2 Increment Account A by $50 Account A: $200 00:01:30 Job Xのleaseが失効 Job X - Incr Account A by $50 Dequeue a job Increment Account A by $50 Account A: $250 Account A: $300 00:02:00 Job X - Account A に $50 追加 - Owner は Worker 1 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Owner は Worker 2 - Lease は 00:02:00 に失効 Job X - Account A に $50 追加 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Lease は 00:02:00 に失効 何らかの理由 (e.g., GC)により 処理が停止・遅延 Finish Job X Finish Job X 二重追加が 本番環境で発生 ...!
  11. 例: Lease-based job queue (stuck & lease失効) Worker 1 Distributed

    Queue Dequeue a job Account DB Job X - Incr Account A by $50 Worker 2 Increment Account A by $50 Account A: $200 00:01:30 Job Xのleaseが失効 Job X - Incr Account A by $50 Dequeue a job Increment Account A by $50 Account A: $250 Account A: $300 00:02:00 Job X - Account A に $50 追加 - Owner は Worker 1 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Owner は Worker 2 - Lease は 00:02:00 に失効 Job X - Account A に $50 追加 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Lease は 00:02:00 に失効 何らかの理由 (e.g., GC)により 処理が停止・遅延 Finish Job X Finish Job X 二重追加が 本番環境で発生 ...!
  12. 例: Lease-based job queue (stuck & lease失効) Worker 1 Distributed

    Queue Dequeue a job Account DB Job X - Incr Account A by $50 Worker 2 Increment Account A by $50 Account A: $200 00:01:30 Job Xのleaseが失効 Job X - Incr Account A by $50 Dequeue a job Increment Account A by $50 Account A: $250 Account A: $300 00:02:00 Job X - Account A に $50 追加 - Owner は Worker 1 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Owner は Worker 2 - Lease は 00:02:00 に失効 Job X - Account A に $50 追加 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Lease は 00:02:00 に失効 何らかの理由 (e.g., GC)により 処理が停止・遅延 Finish Job X Finish Job X 二重追加が 本番環境で発生 ...!
  13. 例: Lease-based job queue (stuck & lease失効) Worker 1 Distributed

    Queue Dequeue a job Account DB Job X - Incr Account A by $50 Worker 2 Increment Account A by $50 Account A: $200 00:01:30 Job Xのleaseが失効 Job X - Incr Account A by $50 Dequeue a job Increment Account A by $50 Account A: $250 Account A: $300 00:02:00 Job X - Account A に $50 追加 - Owner は Worker 1 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Owner は Worker 2 - Lease は 00:02:00 に失効 Job X - Account A に $50 追加 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Lease は 00:02:00 に失効 何らかの理由 (e.g., GC)により 処理が停止・遅延 Finish Job X Finish Job X 二重追加が 本番環境で発生 ...!
  14. 例: Lease-based job queue (stuck & lease失効) Worker 1 Distributed

    Queue Dequeue a job Account DB Job X - Incr Account A by $50 Worker 2 Increment Account A by $50 Account A: $200 00:01:30 Job Xのleaseが失効 Job X - Incr Account A by $50 Dequeue a job Increment Account A by $50 Account A: $250 Account A: $300 00:02:00 二重追加が 本番環境で発生 ...! Job X - Account A に $50 追加 - Owner は Worker 1 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Owner は Worker 2 - Lease は 00:02:00 に失効 Job X - Account A に $50 追加 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Lease は 00:02:00 に失効 何らかの理由 (e.g., GC)により 処理が停止・遅延 Finish Job X Finish Job X
  15. テストは書いたけど… Job QueueからJobを Dequeue して、実行&終了 (Queueから除去)する Consumer を 4 Thread

    起動 Job Queue の初期化等。 Job Lease は4秒経つと失効。 Account A に $50 足す Job を 1000個投入 全ての処理が 終了するまで待機
  16. テストは書いたけど… Job QueueからJobを Dequeue して、実行&終了 (Queueから除去)する Consumer を 4 Thread

    起動 Job Queue の初期化等。 Job Lease は4秒経つと失効。 Account A に $50 足す Job を 1000個投入 全ての処理が 終了するまで待機
  17. テストは書いたけど… Job QueueからJobを Dequeue して、実行&終了 (Queueから除去)する Consumer を 4 Thread

    起動 Job Queue の初期化等。 Job Lease は4秒経つと失効。 Account A に $50 足す Job を 1000個投入 全ての処理が 終了するまで待機
  18. テストは書いたけど… $50追加するJobが1000 Job投入されていたので $50000 == $50 x 1000 で期待通り 本番環境で発生したバグが再現できていない!!

    今回のように問題が発生するケースが 特定できていれば mock等で確実に再 現するテストを作成すべきだね とはいえ、全てのコーナーケースを事前 に把握するのは非常に難しいので、処理 を走らせた状態で、 コードに手を加えず に外部からランダムな遅延を注入して 「何も起こらないか / 何か起こるか」を確 認したい、ね
  19. 極力Javaのコードを書かずに遅延を 注入するには - Byteman - https://byteman.jboss.org/ - 強力。Byteman rule scriptを書くことで何でもできる

    - 内部的にASMを使用 - Chaos-Dukey - https://github.com/komamitsu/chaos-dukey - 簡単。遅延/故障(==例外を投げる)注入に特化 - 内部的にByte Buddyを使用
  20. Worker 1 Distributed Queue Dequeue a job Account DB Job

    X - Incr Account A by $50 Worker 2 Increment Account A by $50 Account A: $200 00:01:30 Job Xのleaseが失効 Job X - Incr Account A by $50 Dequeue a job Increment Account A by $50 Account A: $250 Account A: $300 00:02:00 Job X - Account A に $50 追加 - Owner は Worker 1 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Owner は Worker 2 - Lease は 00:02:00 に失効 Job X - Account A に $50 追加 - Leaseは 00:01:30 に失効 Job X - Account A に $50 追加 - Lease は 00:02:00 に失効 何らかの理由( e.g., GC)により 処理が停止・遅延 Finish Job X Finish Job X Chaos Dukeyを有効化して 先程のテストを実行してみる ↑ これを遅延させれば ..! 二重追加が 本番環境で発生 ...!