Azure SDK for Java の HTTP クライアントとパイプライン
この記事では、Azure SDK for Java 内で HTTP クライアントとパイプライン機能を使用する方法の概要について説明します。 この機能は、すべての Azure SDK for Java ライブラリを使用する開発者向けに、一貫した強力で柔軟なエクスペリエンスを提供します。
HTTP クライアント
Azure SDK for Java は、HttpClient
抽象化を使用して実装されます。 この抽象化により、複数の HTTP クライアント ライブラリまたはカスタム実装を受け入れるプラグ可能なアーキテクチャが可能になります。 ただし、ほとんどのユーザーの依存関係管理を簡略化するために、すべての Azure クライアント ライブラリは azure-core-http-netty
に依存しています。 そのため、Netty HTTP クライアントは、すべての Azure SDK for Java ライブラリで使用される既定のクライアントです。
Netty は既定の HTTP クライアントですが、SDK には、プロジェクトに既に存在する依存関係に応じて、3 つのクライアント実装が用意されています。 これらの実装の目的は次のとおりです。
- Netty
- OkHttp
- JDK 11 で導入された HttpClient
手記
JDK HttpClient
と Azure SDK for Java の組み合わせは、JDK 12 以降でのみサポートされます。
既定の HTTP クライアントを置き換える
別の実装を使用する場合は、Netty をビルド構成ファイルに除外することで、Netty への依存関係を削除できます。 Maven pom.xml ファイルでは、Netty 依存関係を除外し、別の依存関係を含めます。
次の例では、netty 依存関係を azure-security-keyvault-secrets
ライブラリへの実際の依存関係から除外する方法を示します。 次に示すように、Netty をすべての適切な com.azure
ライブラリから除外してください。
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-security-keyvault-secrets</artifactId>
<version>4.2.2.</version>
<exclusions>
<exclusion>
<groupId>com.azure</groupId>
<artifactId>azure-core-http-netty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-core-http-okhttp</artifactId>
<version>1.3.3</version>
</dependency>
手記
Netty 依存関係を削除しても、その代わりに実装を提供しない場合、アプリケーションの起動に失敗します。 HttpClient
実装は、クラスパスに存在する必要があります。
HTTP クライアントを構成する
サービス クライアントをビルドすると、既定では HttpClient.createDefault()
が使用されます。 このメソッドは、提供された HTTP クライアント実装に基づいて、基本的な HttpClient
インスタンスを返します。 プロキシなどのより複雑な HTTP クライアントが必要な場合、各実装には、構成された HttpClient
インスタンスを構築できるビルダーが用意されています。 ビルダーは、NettyAsyncHttpClientBuilder
、OkHttpAsyncHttpClientBuilder
、および JdkAsyncHttpClientBuilder
です。
次の例では、Netty、OkHttp、JDK 11 HTTP クライアントを使用して HttpClient
インスタンスを構築する方法を示します。 これらのインスタンスは、http://localhost:3128
を介してプロキシし、パスワード weakPassword
を使用してユーザー example
で認証します。
// Netty
HttpClient httpClient = new NettyAsyncHttpClientBuilder()
.proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress("localhost", 3128))
.setCredentials("example", "weakPassword"))
.build();
// OkHttp
HttpClient httpClient = new OkHttpAsyncHttpClientBuilder()
.proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress("localhost", 3128))
.setCredentials("example", "weakPassword"))
.build();
// JDK 11 HttpClient
HttpClient client = new JdkAsyncHttpClientBuilder()
.proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress("localhost", 3128))
.setCredentials("example", "weakPassword"))
.build();
構築された HttpClient
インスタンスをサービス クライアント ビルダーに渡して、サービスと通信するためのクライアントとして使用できるようになりました。 次の例では、新しい HttpClient
インスタンスを使用して Azure Storage BLOB クライアントを構築します。
BlobClient blobClient = new BlobClientBuilder()
.connectionString(<connection string>)
.containerName("container")
.blobName("blob")
.httpClient(httpClient)
.build();
管理ライブラリの場合は、マネージャーの構成時に HttpClient
を設定できます。
AzureResourceManager azureResourceManager = AzureResourceManager.configure()
.withHttpClient(httpClient)
.authenticate(credential, profile)
.withDefaultSubscription();
HTTP パイプライン
HTTP パイプラインは、Azure 用 Java クライアント ライブラリの一貫性と診断可能性を実現するための重要なコンポーネントの 1 つです。 HTTP パイプラインは次で構成されます。
- HTTP トランスポート
- HTTP パイプライン ポリシー
クライアントを作成するときに、独自のカスタム HTTP パイプラインを提供できます。 パイプラインを指定しない場合、クライアント ライブラリは、その特定のクライアント ライブラリで動作するように構成されたパイプラインを作成します。
HTTP トランスポート
HTTP トランスポートは、サーバーへの接続を確立し、HTTP メッセージを送受信する役割を担います。 HTTP トランスポートは、Azure SDK クライアント ライブラリが Azure サービスと対話するためのゲートウェイを形成します。 この記事で前述したように、Azure SDK for Java では、既定で http トランスポートに Netty が使用されます。 ただし、SDK にはプラグ可能な HTTP トランスポートも用意されているため、必要に応じて他の実装を使用できます。 また、SDK には、OKHttp と JDK 11 以降に付属する HTTP クライアント用の 2 つの HTTP トランスポート実装も用意されています。
HTTP パイプライン ポリシー
パイプラインは、HTTP 要求/応答ラウンドトリップごとに実行される一連のステップで構成されます。 各ポリシーには専用の目的があり、要求または応答、またはその両方に対して機能します。 すべてのクライアント ライブラリには標準の "Azure Core" レイヤーがあるため、このレイヤーにより、各ポリシーがパイプライン内で順番に実行されます。 要求を送信すると、ポリシーはパイプラインに追加された順序で実行されます。 サービスから応答を受け取ると、ポリシーは逆の順序で実行されます。 パイプラインに追加されたすべてのポリシーは、要求を送信する前と応答を受信した後に実行されます。 ポリシーは、要求、応答、またはその両方に対してアクションを実行するかどうかを決定する必要があります。 たとえば、ログ ポリシーは要求と応答をログに記録しますが、認証ポリシーは要求の変更にのみ関心があります。
Azure Core フレームワークは、ポリシーを実行するために必要なコンテキストと共に、必要な要求と応答のデータをポリシーに提供します。 その後、ポリシーは、指定されたデータで操作を実行し、パイプライン内の次のポリシーにコントロールを渡すことができます。
HTTP パイプラインダイアグラム
HTTP パイプライン ポリシーの位置
クラウド サービスに対して HTTP 要求を行うときは、一時的なエラーを処理し、失敗した試行を再試行することが重要です。 この機能は一般的な要件であるため、Azure Core には、一時的なエラーを監視し、要求を自動的に再試行できる再試行ポリシーが用意されています。
したがって、この再試行ポリシーは、パイプライン全体を 2 つの部分に分割します。再試行ポリシーの前に実行されるポリシーと、再試行ポリシーの後に実行されるポリシーです。 再試行ポリシーの前に追加されたポリシーは、API 操作ごとに 1 回だけ実行され、再試行ポリシーの後に追加されたポリシーは再試行の回数だけ実行されます。
そのため、HTTP パイプラインを構築するときは、要求の再試行ごとにポリシーを実行するか、API 操作ごとに 1 回実行するかを理解する必要があります。
一般的な HTTP パイプライン ポリシー
REST ベースのサービスの HTTP パイプラインには、認証、再試行、ログ記録、テレメトリ、ヘッダー内の要求 ID の指定に関するポリシーを含む構成があります。 Azure Core には、パイプラインに追加できる一般的に必要な HTTP ポリシーが事前に読み込まれています。
政策 | GitHub のリンク |
---|---|
再試行ポリシー | RetryPolicy.java |
認証ポリシー | BearerTokenAuthenticationPolicy.java |
ログ ポリシー | HttpLoggingPolicy.java |
要求 ID ポリシー | RequestIdPolicy.java |
テレメトリ ポリシー | UserAgentPolicy.java |
カスタム HTTP パイプライン ポリシー
HTTP パイプライン ポリシーは、要求と応答を変更または装飾するための便利なメカニズムを提供します。 ユーザーまたはクライアント ライブラリ開発者が作成したパイプラインにカスタム ポリシーを追加できます。 ポリシーをパイプラインに追加するときに、このポリシーを呼び出しごとまたは再試行ごとに実行するかどうかを指定できます。
カスタム HTTP パイプライン ポリシーを作成するには、基本ポリシーの種類を拡張し、抽象メソッドを実装するだけです。 その後、ポリシーをパイプラインにプラグインできます。
HTTP 要求のカスタム ヘッダー
Azure SDK for Java クライアント ライブラリは、次の例に示すように、パブリック API の Context
オブジェクトを通じてカスタマイズされたヘッダーを定義する一貫した方法を提供します。
// Add your headers
HttpHeaders headers = new HttpHeaders();
headers.set("my-header1", "my-header1-value");
headers.set("my-header2", "my-header2-value");
headers.set("my-header3", "my-header3-value");
// Call API by passing headers in Context.
configurationClient.addConfigurationSettingWithResponse(
new ConfigurationSetting().setKey("key").setValue("value"),
new Context(AddHeadersFromContextPolicy.AZURE_REQUEST_HTTP_HEADERS_KEY, headers));
// The three headers are now be added to the outgoing HTTP request.
詳細については、AddHeadersFromContextPolicy クラスを参照してください。
既定の TLS/SSL ライブラリ
既定では、すべてのクライアント ライブラリで Tomcat ネイティブのボーリング SSL ライブラリを使用して、TLS/SSL 操作のネイティブ レベルのパフォーマンスを有効にします。 ボーリング SSL ライブラリは、Linux、macOS、および Windows 用のネイティブ ライブラリを含む uber JAR であり、JDK 内の既定の TLS/SSL 実装と比較してパフォーマンスが向上します。
TLS/SSL 依存関係 Tomcat-Native サイズを小さくする
既定では、Azure SDK for Java では、Tomcat-Native Boring SSL ライブラリの uber JAR が使用されます。 この依存関係のサイズを小さくするには、次の例に示すように、netty-tcnative に従って、os
分類子との依存関係を含める必要があります。
<project>
...
<dependencies>
...
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
<version>2.0.25.Final</version>
<classifier>${os.detected.classifier}</classifier>
</dependency>
...
</dependencies>
...
<build>
...
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.4.0.Final</version>
</extension>
</extensions>
...
</build>
...
</project>
JDK TLS/SSL を使用する
Tomcat-Native ボーリング SSL ではなく既定の JDK TLS/SSL を使用する場合は、Tomcat ネイティブのボーリング SSL ライブラリを除外する必要があります。 テストに基づいて、JDK TLS/SSL のパフォーマンスは、Tomcat-Native のボーリング SSL と比較して 30% 低速であることに注意してください。 com.azure:azure-core:1.28.0
以降を使用すると、HttpClient
実装ライブラリ (com.azure:azure-core-http-netty
など) によって、Tomcat-Native Boring SSL への依存関係が管理されます。 依存関係を除外するには、POM ファイルに次の構成を追加します。
<project>
...
<dependencies>
...
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-core-http-netty</artifactId>
<version>1.13.6</version>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
</exclusion>
</exclusions>
</dependency>
...
</dependencies>
...
</project>
次の手順
Azure SDK for Java の HTTP クライアント機能について理解したら、使用している HTTP クライアントをさらにカスタマイズする方法について説明します。 詳細については、「Azure SDK for Javaでプロキシを構成する」を参照してください。