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 提供三种客户端实现,具体取决于在项目中已经拥有的依赖项。 这些实现适用于:
注意
JDK HttpClient
与用于 Java 的 Azure SDK 结合使用,仅 JDK 12 及更高版本受支持。
替换默认 HTTP 客户端
如果想要使用另一种实现,则可以通过在生成配置文件中排除某个依赖项来删除 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.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 依赖项但未就地提供任何实现,应用程序将无法启动。 classpath 上必须存在 HttpClient
实现。
配置 HTTP 客户端
生成服务客户端时,默认使用 HttpClient.createDefault()
。 此方法基于提供的 HTTP 客户端实现返回基本 HttpClient
实例。 对于需要更复杂的 HTTP 客户端(例如代理)的情况,每种实现都提供一个生成器,让你能够构造经过配置的 HttpClient
实例。 生成器包括 NettyAsyncHttpClientBuilder
、OkHttpAsyncHttpClientBuilder
和 JdkAsyncHttpClientBuilder
。
以下示例演示如何使用 Netty、OkHttp 和 JDK 11 HTTP 客户端生成 HttpClient
实例。 这些实例通过 http://localhost:3128
代理并使用用户 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 11 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();
对于管理库,可在管理器配置过程中设置 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 默认为其 HTTP 传输使用 Netty。 但是,该 SDK 还提供可插入的 HTTP 传输,因此可在适当情况下使用其他实现。 SDK 还为 OkHttp 和 JDK 11 及更高版本随附的 HTTP 客户端提供另外两种 HTTP 传输实现。
HTTP 管道策略
管道由为每个 HTTP 请求-响应往返执行的一系列步骤组成。 每个策略都有专用用途,并针对请求或响应执行操作,有时也可以同时执行这两项操作。 因为所有客户端库都具有标准“Azure Core”层,所以此层可确保每个策略在管道中按顺序执行。 当你发送请求时,策略将按照它们添加到管道中的顺序执行。 当你接收来自服务的响应时,策略将按相反的顺序执行。 添加到管道的所有策略都在发送请求之前和接收响应之后执行。 策略必须决定是处理请求还是响应,还是同时处理两者。 例如,日志记录策略记录请求和响应,但身份验证策略仅对修改请求感兴趣。
Azure Core 框架为策略提供所需的请求和响应数据以及执行策略所需的任何上下文。 该策略随后可通过给定的数据执行其操作,并将控制措施传递到管道中的下一个策略。
HTTP 管道策略位置
向云服务发出 HTTP 请求时,必须处理暂时性故障以及重试失败的尝试。 因为此功能是常见要求,所以 Azure Core 提供可监视暂时性故障并自动重试请求的重试策略。
因此,此重试策略将整个管道拆分为两个部分:在重试策略之前执行的策略,以及在重试策略之后执行的策略。 在重试策略之前添加的策略只会针对每个 API 操作执行一次,而在重试策略之后添加的策略将按重试的次数执行。
因此,在生成 HTTP 管道时,应了解是针对每次请求重试执行某个策略,还是针对每个 API 操作执行一次策略。
常用 HTTP 管道策略
基于 REST 的服务的 HTTP 管道具有用于身份验证、重试、日志记录、遥测以及在标头中指定请求 ID 的策略配置。 Azure Core 预加载了可添加到管道的这些常用 HTTP 策略。
策略 | GitHub 链接 |
---|---|
重试策略 | RetryPolicy.java |
身份验证策略 | BearerTokenAuthenticationPolicy.java |
日志记录策略 | HttpLoggingPolicy.java |
请求 ID 策略 | 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 库是一个 uber JAR,包含适用于 Linux、macOS 和 Windows 的本机库,与 JDK 中的默认 TLS/SSL 实现相比,可提供更好的性能。
减少 Tomcat-Native TLS/SSL 依赖项大小
默认情况下,Tomcat-Native Boring SSL 库的 uber JAR 用于 Java 的 Azure SDK。 若要减小此依赖项的大小,需要根据 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
如果你宁愿使用默认的 JDK TLS/SSL 而不是 Tomcat-Native Boring SSL,则需要排除 Tomcat 本机 Boring SSL 库。 请注意,根据我们的测试,JDK TLS/SSL 的性能比 Tomcat-Native Boring 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 中的代理。