適用於 Java 的 Azure SDK 中的 HTTP 用戶端和管線

本文提供在 Azure SDK for Java 中使用 HTTP 用戶端和管線功能的概觀。 這項功能可為使用所有適用於 Java 的 Azure SDK 程式庫的開發人員提供一致、強大且彈性的體驗。

HTTP 用戶端

適用於 Java 的 Azure SDK 是使用 HttpClient 抽象概念來實作。 此抽象概念可讓插入式架構接受多個 HTTP 用戶端連結庫或自定義實作。 不過,為了簡化大部分使用者的相依性管理,所有 Azure 用戶端連結庫都相依於 azure-core-http-netty。 因此, Netty HTTP 用戶端是所有適用於 Java 的 Azure SDK 連結庫中使用的預設用戶端。

這很重要

確保您的 azure-core-http-netty 相依性使用 1.15.12 或更高版本。 如果您使用 BOM,請確定您的 BOM 版本至少為 1.2.36

需要此最低版本,才能在長時間執行的作業期間啟用 Azure Resource Manager 傳回的大型 HTTP 標頭。

雖然 Netty 是預設 HTTP 用戶端,但 SDK 提供三個用戶端實作,視您在專案中已有的相依性而定。 這些實作適用於:

備註

JDK HttpClient 搭配適用於 Java 的 Azure SDK 僅支援 JDK 12 和更新版本。

取代預設 HTTP 用戶端

如果你偏好其他實作,可以在建置設定檔中將 Netty 排除,以移除對 Netty 的相依性。 在 Maven pom.xml 檔案中,排除 Netty 相性,並加入另一個相依性。

以下範例說明如何從對 azure-security-keyvault-secrets 函式庫的實際相依性中排除 Netty 相依性。 請務必從所有適當的 com.azure 函式庫中排除 Netty,如範例所示:

<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-security-keyvault-secrets</artifactId>
    <version>4.9.4</version>
    <exclusions>
      <exclusion>
        <groupId>com.azure</groupId>
        <artifactId>azure-core-http-netty</artifactId>
      </exclusion>
    </exclusions>
</dependency>

<!-- OkHttp -->
<dependency>
  <groupId>com.azure</groupId>
  <artifactId>azure-core-http-okhttp</artifactId>
  <version>1.12.10</version>
</dependency>

<!-- JDK HttpClient -->
<dependency>
  <groupId>com.azure</groupId>
  <artifactId>azure-core-http-jdk-httpclient</artifactId>
  <version>1.0.3</version>
</dependency>

備註

如果您移除 Netty 相依性,但未在其位置提供任何實作,則應用程式無法啟動。 類別路徑上必須有 HttpClient 實作。

設定 HTTP 用戶端

當您建置服務用戶端時,預設會使用 HttpClient.createDefault()。 此方法會根據提供的 HTTP 用戶端實作傳回基本 HttpClient 實例。 如果你需要更複雜的 HTTP 客戶端,例如代理伺服器,每個實作都提供一個建構器,可以用來建構配置 HttpClient 的實例。 建造者是 NettyAsyncHttpClientBuilderOkHttpAsyncHttpClientBuilderJdkAsyncHttpClientBuilder

以下範例展示了如何使用 Netty、OkHttp 和 JDK HTTP 用戶端來建構 HttpClient 實例。 這些實例會透過 http://localhost:3128 Proxy,並使用密碼 example向使用者 weakPassword 進行驗證。

// 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 HttpClient
HttpClient client = new JdkAsyncHttpClientBuilder()
    .proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress("localhost", 3128))
        .setCredentials("example", "weakPassword"))
    .build();

您現在可以將建構的 HttpClient 實例傳遞至服務客戶端產生器,以做為與服務通訊的用戶端。 下列範例會使用新的 HttpClient 實例來建置 Azure 記憶體 Blob 用戶端。

BlobClient blobClient = new BlobClientBuilder()
    .connectionString(<connection string>)
    .containerName("container")
    .blobName("blob")
    .httpClient(httpClient)
    .build();

針對管理程式庫,請在設定 Manager 時設定 HttpClient

AzureResourceManager azureResourceManager = AzureResourceManager.configure()
    .withHttpClient(httpClient)
    .authenticate(credential, profile)
    .withDefaultSubscription();

HTTP 管線

HTTP 管線是達成 Azure Java 用戶端連結庫中一致性和可診斷性的重要元件之一。 HTTP 管線由以下元件組成:

  • HTTP 傳輸協定
  • HTTP 管線原則

您可以在建立用戶端時提供自己的自訂 HTTP 管線。 如果您沒有提供管線,客戶端程式庫會建立一個管線,並將其設定為與該程式庫一起使用。

HTTP 傳輸

HTTP 傳輸負責建立與伺服器的連線,以及傳送和接收 HTTP 訊息。 HTTP 傳輸作為 Azure SDK 用戶端程式庫與 Azure 服務互動的閘道。 如本文稍早所述,Azure SDK for Java 預設會使用 Netty 進行 HTTP 傳輸。 不過,SDK 也提供插入式 HTTP 傳輸,因此您可以在適當的情況下使用其他實作。 SDK 也為 OkHttp 提供兩個 HTTP 傳輸實作,以及 JDK 11 和更新版本隨附的 HTTP 用戶端。

HTTP 管線原則

管道由針對每個 HTTP 請求和回應的往返過程執行的一系列步驟組成。 每個政策都有專用的用途,並在請求、回應或有時同時針對兩者採取行動。 由於所有客戶端連結庫都有標準 『Azure Core』 層,因此此層可確保每個原則在管線中依序執行。 當您傳送要求時,政策會依新增至管線的順序執行。 當您收到來自服務的回應時,原則會以反向順序執行。 新增至管線的所有策略都會在您發送請求之前以及收到回應之後執行。 原則必須決定是否要根據要求、回應或兩者採取行動。 例如,記錄原則會記錄要求和回應,但驗證原則只對修改要求感興趣。

Azure Core 架構會提供原則所需的要求和響應數據,以及執行原則的任何必要內容。 然後,策略可以使用指定的數據執行其作業,並將控制權傳遞給流程中的下一個策略。

Azure SDK for Java 中 HTTP 管線的截圖,顯示請求與回應的傳輸與政策執行順序。

HTTP 管線政策位置

當您對雲端服務提出 HTTP 要求時,請務必處理暫時性失敗,並重試失敗的嘗試。 由於這項功能是常見的需求,Azure Core 會提供重試原則,可監看暫時性失敗,並自動重試要求。

因此,此重試原則會將整個管線分割成兩個部分:重試原則之前執行的原則,以及重試原則之後執行的原則。 若在重試原則之前新增的原則,每個 API 作業只執行一次;而在重試原則之後新增的原則,其執行次數則為重試的次數。

因此,在建立 HTTP 管線時,您應該瞭解何時要針對每次要求重試或每個 API 作業執行一次原則。

常見的 HTTP 管線原則

REST 型服務的 HTTP 管線具有驗證、重試、記錄、遙測,以及在標頭中指定要求標識碼的原則設定。 Azure Core 包含下列可新增至管線的常用 HTTP 原則。

原則 GitHub 連結
重試原則 RetryPolicy.java
驗證原則 BearerTokenAuthenticationPolicy.java
記錄原則 HttpLoggingPolicy.java
請求識別碼政策 RequestIdPolicy.java
遙測原則 UserAgentPolicy.java

自定義 HTTP 管線原則

HTTP 管線原則提供方便的機制來修改或裝飾要求和回應。 你可以在你或客戶端函式庫開發者建立的管線中新增自訂政策。 將此原則新增至管線時,您可以指定此原則應在每次呼叫時執行,還是在每次重試時執行。

要建立自訂的 HTTP 管線政策,可以擴充一個基礎政策型別並實作一些抽象方法。 然後,您可以將策略放入管線。

HTTP 要求中的自定義標頭

適用於 Java 的 Azure SDK 客戶端程式庫提供一致的方法,透過公用 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 原生的 Boring SSL 函式庫。 此函式庫提供原生層級的 TLS/SSL 效能。 Boring SSL 函式庫是一個超 JAR,包含 Linux、macOS 和 Windows 的原生函式庫。 它在 JDK 中提供較佳的效能,優於 JDK 內建的 TLS/SSL 實作。

減少 Tomcat-Native 的 TLS/SSL 依賴性大小

根據預設,適用於 Java 的 Azure SDK 會使用 Tomcat-Native Boring SSL 程式庫的 uber JAR 檔。 若要縮小此相依性的大小,請依照 netty-tcnative 中的說明,納入具有 os classifier 的相依性,如下例所示:

<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

如果你偏好使用預設的 JDK TLS/SSL,而非 Tomcat-Native Boring SSL,請排除 Tomcat 原生的 Boring SSL 函式庫。 根據測試,與 Tomcat-Native Boring SSL 相比,JDK TLS/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>

後續步驟

現在您已熟悉適用於 Java 的 Azure SDK 中的 HTTP 用戶端功能,接下來請瞭解如何進一步自定義您使用的 HTTP 用戶端。 如需詳細資訊,請參閱 在 Azure SDK for Java 中設定 Proxy