Clientes e pipelines HTTP no SDK do Azure para Java

Este artigo apresenta uma visão geral do uso da funcionalidade de cliente HTTP e pipeline no SDK do Azure para Java. Essa funcionalidade proporciona uma experiência consistente, eficiente e flexível para os desenvolvedores que usam todas as bibliotecas do SDK do Azure para Java.

Clientes HTTP

O SDK do Azure para Java é implementado usando uma abstração de HttpClient. Essa abstração permite uma arquitetura conectável que aceita várias bibliotecas de clientes HTTP ou implementações personalizadas. No entanto, para simplificar o gerenciamento de dependência para a maioria dos usuários, todas as bibliotecas de clientes do Azure dependem de azure-core-http-netty. Dessa forma, o cliente HTTP do Netty é o cliente padrão usado em todas as bibliotecas do SDK do Azure para Java.

Embora a sub-rede seja o cliente HTTP padrão, o SDK oferece três implementações de cliente conforme as dependências que você já tem no projeto. Essas implementações são para:

Observação

O JDK em combinação com o SDK do Azure para Java só tem suporte com o JDK HttpClient 12 e superior.

Substituir o cliente HTTP padrão

Se você preferir outra implementação, poderá remover a dependência da sub-rede, excluindo-a nos arquivos de configuração de build. Em um arquivo pom.xml do Maven, você exclui a dependência de sub-rede e inclui outra dependência.

O exemplo a seguir mostra como excluir a dependência de uma sub-rede de uma dependência real da biblioteca de azure-security-keyvault-secrets. Exclua a sub-rede de todas as bibliotecas de com.azure apropriadas, conforme mostrado aqui:

<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>

Observação

Se você remover a dependência Netty, mas não fornecer nenhuma implementação em seu lugar, o aplicativo falhará ao iniciar. Uma implementação de HttpClient deve existir no classpath.

Configurar clientes HTTP

Quando você cria um cliente de serviço, o padrão é usar HttpClient.createDefault()o . Esse método retorna uma instância básica do HttpClient com base na implementação do cliente HTTP fornecida. Caso você precise de um cliente HTTP mais complexo, como um proxy, cada implementação oferece um construtor que permite construir uma instância de HttpClient configurada. Os construtores são NettyAsyncHttpClientBuilder, OkHttpAsyncHttpClientBuilder e JdkAsyncHttpClientBuilder.

Os exemplos a seguir mostram como criar instâncias HttpClient usando a Netty, OkHttp e o cliente HTTP do JDK 11. Essas instâncias realizam proxy por meio de http://localhost:3128 e autenticam-se com o usuário example com a senha 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();

Agora você pode passar a instância de HttpClient construída para um construtor de cliente de serviço para uso como o cliente para comunicação com o serviço. O exemplo a seguir usa a nova instância de HttpClient para criar um cliente do Azure Storage Blob.

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

Para bibliotecas de gerenciamento, você pode definir o HttpClient durante a configuração do Gerenciador.

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

Pipeline HTTP

O pipeline HTTP é um dos principais componentes para alcançar consistência e capacidade de diagnóstico nas bibliotecas de clientes Java para o Azure. Um pipeline HTTP é composto por:

  • Um transporte HTTP
  • Políticas de pipeline HTTP

Você pode fornecer o seu pipeline HTTP personalizado ao criar um cliente. Se você não fornecer um pipeline, a biblioteca do cliente criará um configurado para funcionar com essa biblioteca de cliente específica.

Transporte HTTP

O transporte HTTP é responsável por estabelecer a conexão com o servidor e enviar e receber mensagens HTTP. O transporte HTTP forma o gateway para que as bibliotecas de clientes do SDK do Azure interajam com os serviços do Azure. Conforme observado anteriormente neste artigo, o SDK do Azure para Java usa o Netty por padrão para o transporte HTTP. No entanto, o SDK também fornece um transporte HTTP conectável para que você possa usar outras implementações, quando apropriado. O SDK também fornece mais duas implementações de transporte HTTP para OkHttp e o cliente HTTP fornecido com o JDK 11 e posterior.

Políticas de pipeline HTTP

Um pipeline consiste em uma sequência de etapas executadas para cada viagem de ida e volta de solicitação-resposta HTTP. Cada política tem um propósito específico e atua em uma solicitação ou resposta ou, às vezes, em ambas. Como todas as bibliotecas de cliente têm uma camada "Azure Core" padrão, essa camada garante que cada política seja executada na ordem no pipeline. Quando você envia uma solicitação, as políticas são executadas na ordem em que são adicionadas ao pipeline. Quando você recebe uma resposta do serviço, as políticas são executadas na ordem inversa. Todas as políticas adicionadas ao pipeline são executadas antes de você enviar a solicitação e depois de receber uma resposta. A política precisa decidir se deve agir na solicitação, na resposta ou em ambas. Por exemplo, uma política de log registra a solicitação e a resposta, mas a política de autenticação só está interessada em modificar a solicitação.

A estrutura do Azure Core fornece à política os dados de solicitação e resposta necessários, juntamente com qualquer contexto necessário para executar a política. A política então pode executar sua operação com os dados fornecidos e passar o controle junto com a próxima política no pipeline.

HTTP pipeline diagram

Posição da política de pipeline HTTP

Quando você faz solicitações HTTP para serviços de nuvem, é importante lidar com falhas transitórias e repetir tentativas com falha. Como essa funcionalidade é um requisito comum, o Azure Core fornece uma política de repetição que pode observar falhas transitórias e repetir a solicitação automaticamente.

Essa política de repetição, portanto, divide todo o pipeline em duas partes: políticas executadas antes da política de repetição e políticas executadas após a política de repetição. As políticas adicionadas antes da política de repetição são executadas apenas uma vez por operação de API, enquanto as políticas adicionadas após a política de repetição são executadas o mesmo número de vezes que as novas tentativas.

Portanto, ao criar o pipeline HTTP, você deve entender se deseja executar uma política para cada repetição de solicitação ou uma vez por operação da API.

Políticas comuns de pipeline HTTP

Pipelines HTTP para serviços baseados em REST têm configurações com políticas de autenticação, repetições, registro em log, telemetria e especificação da ID da solicitação no cabeçalho. O Azure Core é pré-carregado com essas políticas HTTP comumente necessárias que você pode adicionar ao pipeline.

Política Link do GitHub
Política de repetição RetryPolicy.java
política de autenticação BearerTokenAuthenticationPolicy.java
Política de registro em log HttpLoggingPolicy.java
política de ID de solicitação RequestIdPolicy.java
Política de telemetria UserAgentPolicy.java

Política de pipeline HTTP personalizada

A política de pipeline HTTP oferece um mecanismo conveniente para modificar ou decorar a solicitação e a resposta. Você pode adicionar políticas personalizadas ao pipeline que o usuário ou o desenvolvedor da biblioteca do cliente criou. Ao adicionar a política ao pipeline, você pode especificar se ela deve ser executada por chamada ou por repetição.

Para criar uma política de pipeline HTTP personalizada, basta estender um tipo de política de base e implementar algum método abstrato. Você pode então conectar a política ao pipeline.

Cabeçalhos personalizados em solicitações HTTP

As bibliotecas de cliente do SDK do Azure para Java fornecem uma maneira consistente de definir cabeçalhos personalizados por meio Context de objetos na API pública, conforme mostrado no exemplo a seguir:

// 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.

Para obter mais informações, consulte AddHeadersFromContextPolicy Class.

Biblioteca TLS/SSL padrão

Todas as bibliotecas cliente, por padrão, usam a biblioteca SSL Boring nativa do Tomcat para habilitar o desempenho de nível nativo para operações TLS/SSL. A biblioteca SSL Boring é um JAR que contém bibliotecas nativas para Linux, macOS e Windows, e fornece melhor desempenho em comparação com a implementação TLS/SSL padrão dentro do JDK.

Reduzir o tamanho da dependência TLS/SSL nativa do Tomcat

Por padrão, o JAR uber da biblioteca SSL do Tomcat-Native Boring é usado nos SDKs do Azure para Java. Para reduzir o tamanho dessa dependência, você precisa incluir a dependência com um os classificador conforme netty-tcnative, conforme mostrado no exemplo a seguir:

<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>

Usar JDK TLS/SSL

Se você preferir usar o JDK TLS/SSL padrão em vez do Tomcat-Native Boring SSL, será necessário excluir a biblioteca SSL Boring nativa do Tomcat. Esteja ciente de que, com base em nossos testes, o desempenho do JDK TLS/SSL é 30% mais lento em comparação com o Tomcat-Native Boring SSL. Quando você usa com.azure:azure-core:1.28.0 ou posterior, a biblioteca -implementing (como com.azure:azure-core-http-netty) gerencia a HttpClientdependência do Tomcat-Native Boring SSL. Para excluir a dependência, adicione a seguinte configuração ao arquivo 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>

Próximas etapas

Agora que você está familiarizado com a funcionalidade do cliente HTTP no SDK do Azure para Java, saiba como personalizar ainda mais o cliente HTTP que você está usando. Para obter mais informações, consulte Configurar proxies no SDK do Azure para Java.