1 つのスレッドがプロキシプロパティを設定し、リクエストを送り、元の値を復元します。別のスレッドが別のプロキシで同じことをします。上から下へ読むとコードは整って見えますが、両方のスレッドが共有 JVM 状態を変更しています。

System.setProperty() はプロセスに対するシステムプロパティを変更します。呼び出したスレッドに経路を結び付けるわけではありません。並行するリクエストは、別の作業のために書かれた値を目にすることがあり、既存のクライアントはすでに独自の設定を取り込んでいる可能性があります。

経路をクライアントの一部にする

Java の HTTP クライアントでは、意図的なプロキシセレクターを使ってクライアントを作成します。ワークロードが異なるルーティングポリシーを必要とする場合は、クライアントを分けておきます:

HttpClient client = HttpClient.newBuilder()
    .proxy(ProxySelector.of(
        new InetSocketAddress("203.0.113.10", 8080)))
    .connectTimeout(Duration.ofSeconds(5))
    .build();

インポートは java.net、java.net.http、java.time です。アドレスは例示です。許可された公開経路のテストには、HTTP プロキシ一覧が候補エンドポイントを提供します。リクエストの期限とプロキシ認証は、アプリケーションの必要に応じて別々に設定してください。

ビルダーの proxy メソッドはクライアント単位の選択を記録します。そのため、非同期操作の周りにグローバルな書き込みを並べるより、ポリシーを検査しやすくなります。

グローバル設定にも用途はある

参加するすべてのクライアントが従うべき場合は、JVM 全体で 1 つのプロキシポリシーが適切なことがあります。アプリケーションの起動時にそのポリシーを設定し、どのライブラリがそれを尊重するかを確認してください。

問題は、グローバルプロパティを個々のリクエストの一時的な切り替えとして使うときに生じます。サーバーでは、自分のメソッドが同期に見えても、バックグラウンドワーカーやライブラリ呼び出しが並行して実行されることがあります。ルーティング状態は接続を所有するクライアントまたはコネクターに保持し、別のリクエストが作業の途中で変更できないようにしてください。

関連記事