その「1回限り」、同時アクセスでも守れますか?―AI推論型AppSecとBlazeMeterで進める継続的検証
「クーポンは1人1回まで」
画面に表示された通り、通常の操作では2回目は拒否される。それでも、ほぼ同時に届いた複数のリクエストに対しては、同じ制約が守られるとは限りません。
二つの処理がどちらも「まだ利用していない」と確認した後、それぞれが割引を適用してしまう―単独の操作では正常に見えても、同時実行によって業務ルールが崩れる場合があります。クーポンに限らず、在庫の引き当て、ポイントの付与、送金、返金でも同じような問題が発生します。
このような問題を開発の早い段階で見つけるには、コードの変更によって何が起こるかを読み解き、実際に同時実行させて確かめることが有効です。本記事では、AI推論型AppSecによるコード解析と、Perforce BlazeMeterの負荷テスト機能を組み合わせる検証方法をご紹介します。
コードを読んで、検証すべき「変更」を見つける
一般的な静的解析は、既知の脆弱性パターンや危険なデータフローの検出に強みがあります。一方、「1人1回」という業務ルールが守られるかを考えるには、利用回数の確認、更新、注文への割引適用など、複数の処理の関係を理解する必要があります。
例えば、プルリクエストでクーポンの利用判定と更新処理が変更された場合、レビューでは次のような問いを立てられます。
- 利用回数の確認と更新は、同時アクセス時にも一つだけ実行されるか
- 同じ注文に対する再送や並列リクエストで、割引が重複しないか
- エラーを返した場合でも、決済や記録の更新だけが進んでいないか
AI推論型AppSecは、変更箇所だけでなく関連する処理やデータの文脈を読み、こうした検討すべき箇所を特定する助けになります。ただし、コード解析の指摘だけで実際の発生条件や業務影響が確定するわけではありません。そこで次に、実行時の振る舞いをテストします。
コードの文脈を読む考え方については、関連記事「なぜ従来のSASTだけでは業務ロジックの脆弱性を見つけにくいのか?AIが読み解く「文脈と変更」」でも紹介しています。
BlazeMeterで「同時でも1回だけ」を検証する
BlazeMeterでは、JMeterなどで作成したシナリオを活用し、複数のリクエストを実行できます。ここでは説明用の例として、同じユーザー・同じクーポン・同じ注文に対して50件のリクエストをほぼ同時に送るシナリオを考えます。
単一の負荷生成エンジン上でJMeterのSynchronizing Timerなどを使って送信タイミングを揃え、実際に送信できた件数と時刻を確認します。テスト前には、利用回数と注文状態を記録しておきます。この例で「最初の1件のみ成功し、それ以外は競合として拒否する」という仕様を定めた場合、確認項目は次のようになります。
| 確認項目 | 期待する結果 |
|---|---|
| APIの応答 | 成功は1件、残りは仕様に定めた競合応答などを返す |
| クーポンの利用回数 | 1回だけ増える |
| 注文への割引 | 1回だけ適用される |
| 決済などの後続処理 | 実行・記録が重複しない |
大切なのは、応答コードだけで合格にしないことです。49件が仕様どおりに競合応答を返していても、裏側で割引や決済が複数回実行されていれば、業務上の問題は残ります。テスト後に確認APIやデータを照合し、最終的な業務状態が1回分だけ変化したかまで確かめます。
なお、再送時に同じ処理結果を返す設計など、APIの仕様によって期待する応答件数やステータスは異なります。「50件中1件成功」はすべてのシステムに共通する合格基準ではありません。守るべき業務ルールを明確にし、APIの応答だけでなく、利用回数や割引など、処理後の状態も確認します。これは、最大処理能力を測る大規模な負荷試験ではなく、負荷テスト機能を使った競合状態の検証です。
LLM APIも、早い段階から異常系を試す
同じ早期検証の考え方は、外部サービスへの依存にも当てはまります。生成AIを組み込んだアプリケーションでは、外部のLLM APIが遅くなったり、レート制限でHTTP 429エラー(Too Many Requests)を返す時の挙動も重要です。無制限に再試行すれば、利用者の待ち時間だけでなく、外部APIの呼び出し回数や費用まで増える恐れがあります。コード解析では再試行回数、タイムアウト、同時呼び出し数などの変更に着目し、実行テストで設定どおりに動くかを確認できます。
しかし、負荷テストのたびに実際のLLM APIへ大量のリクエストを送ると、従量課金やレート制限が試験の制約になります。外部サービスの利用条件にも配慮が必要です。BlazeMeterのサービス仮想化(Service Virtualization)を使えば、通常応答に加え、遅延、タイムアウト、サーバーエラーなどを制御した応答として用意できます。負荷テストや機能テストの実行時に、アプリケーションが仮想サービスへ接続するよう設定して検証します。
例えばタイムアウトの応答を返すシナリオなら、「再試行は規定回数以内か」、「待機時間は適切か」、「利用者にはどのような結果を返すか」を確認できます。仮想サービスは、自社アプリケーションの制御ロジックを繰り返し試すための手段です。実際のLLMの回答品質や外部サービスそのものの性能は、別途、実サービスを用いて確認する必要があります。
公式資料でも、LLM APIのテストで仮想応答を利用し、非本番環境のトークン消費を抑える方法が紹介されています。仮想サービスでは応答遅延を設定でき、レート制限による429エラーの応答も再現できます。仮想サービスはBlazeMeterのテスト設定から選択し、テスト対象アプリケーションの接続先が仮想サービスを向いていることを確認して利用します。
小さなテストを継続できる運用へ
開発の早い段階で始めるなら、全機能を一度に大規模試験する必要はありません。まずは、クーポンの利用回数制限など、守るべきルールが明確な機能を一つ選び、変更内容の確認からテスト、修正後の再検証までを次の手順で進めます。
- Pull Requestの変更から、守るべき業務ルールと影響を受ける処理を確認する
- 同時実行や外部APIの異常時に何が起きるべきかを、テストの期待結果として定める
- BlazeMeterでシナリオを実行し、応答時間・エラーだけでなく最終的な業務状態も確認する
- 修正後に同じ条件で再実行し、結果を比較する
仮想サービスの試験条件をチームで管理する面でも、BlazeMeterは機能を拡充しています。2026年8月のアップデート(Release 3.2)にて、仮想サービストランザクションの変更履歴、差分比較、復元が追加されました。例えば、429エラーの応答を返す条件を変更した際にも、過去の設定との差分を確認できます。
まとめ
コードを読むことで「どこを確かめるべきか」を考え、負荷テストの仕組みで「実際にどう動くか」を確認する。この二つをつなぐと、通常の操作では見えにくい業務ロジックの問題やLLM APIの異常時に起きる問題に対して、開発中から取り組めます。
特に競合状態の検証では、リクエストの成功・失敗だけでなく、利用回数、割引、決済といった業務上の結果が正しいことが合格条件です。変更時に小さく試し、修正後に同じ条件で確かめる。その積み重ねがリリース直前の手戻りを減らすことにつながります。