Compartir vía


Clientes y canalizaciones HTTP en el SDK de Azure para Java

En este artículo se proporciona información general sobre el uso del cliente HTTP y la funcionalidad de canalización dentro del SDK de Azure para Java. Esta funcionalidad proporciona una experiencia coherente, eficaz y flexible para los desarrolladores que usan todas las bibliotecas de Azure SDK para Java.

Clientes HTTP

El SDK de Azure para Java se implementa mediante una abstracción HttpClient. Esta abstracción permite una arquitectura conectable que acepta varias bibliotecas de cliente HTTP o implementaciones personalizadas. Sin embargo, para simplificar la administración de dependencias para la mayoría de los usuarios, todas las bibliotecas cliente de Azure dependen de azure-core-http-netty. Por lo tanto, el cliente HTTP de Netty es el cliente predeterminado que se usa en todas las bibliotecas de Azure SDK para Java.

Aunque Netty es el cliente HTTP predeterminado, el SDK proporciona tres implementaciones de cliente, en función de las dependencias que ya tenga en el proyecto. Estas implementaciones son para:

Nota

El HttpClient JDK en combinación con el SDK de Azure para Java solo se admite con JDK 12 y versiones posteriores.

Reemplazar el cliente HTTP predeterminado

Si prefiere otra implementación, puede quitar la dependencia en Netty excluyendola en los archivos de configuración de compilación. En un archivo de pom.xml de Maven, se excluye la dependencia de Netty e incluye otra dependencia.

En el ejemplo siguiente se muestra cómo excluir la dependencia de Netty de una dependencia real en la biblioteca de azure-security-keyvault-secrets. Asegúrese de excluir Netty de todas las bibliotecas de com.azure adecuadas, como se muestra aquí:

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

Nota

Si quita la dependencia de Netty pero no proporciona ninguna implementación en su lugar, la aplicación no se puede iniciar. Debe existir una implementación de HttpClient en la ruta de clase.

Configuración de clientes HTTP

Al compilar un cliente de servicio, el valor predeterminado es usar HttpClient.createDefault(). Este método devuelve una instancia de HttpClient básica basada en la implementación del cliente HTTP proporcionada. En caso de que necesite un cliente HTTP más complejo, como un proxy, cada implementación ofrece un generador que le permite construir una instancia de HttpClient configurada. Los generadores son NettyAsyncHttpClientBuilder, OkHttpAsyncHttpClientBuilder y JdkAsyncHttpClientBuilder.

En los ejemplos siguientes se muestra cómo compilar instancias de HttpClient mediante Netty, OkHttp y el cliente HTTP JDK 11. Estas instancias utilizan un proxy a través de http://localhost:3128 y se autentican con el usuario example y la contraseña 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();

Ahora puede pasar la instancia de HttpClient construida a un generador de cliente del servicio para su uso como cliente para comunicarse con el servicio. En el ejemplo siguiente se usa la nueva instancia de HttpClient para compilar un cliente de blobs de Azure Storage.

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

En el caso de las bibliotecas de administración, puede establecer el HttpClient durante la configuración del Gestor.

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

Canalización HTTP

La canalización HTTP es uno de los componentes clave para lograr la coherencia y el diagnóstico en las bibliotecas cliente de Java para Azure. Una canalización HTTP se compone de:

  • Un transporte HTTP
  • Directivas de canalización HTTP

Puede proporcionar su propia canalización HTTP personalizada al crear un cliente. Si no proporciona una canalización, la biblioteca cliente crea una configurada para trabajar con esa biblioteca cliente específica.

Transporte HTTP

El transporte HTTP es responsable de establecer la conexión al servidor y enviar y recibir mensajes HTTP. El transporte HTTP forma la puerta de enlace de las bibliotecas cliente del SDK de Azure para interactuar con los servicios de Azure. Como se indicó anteriormente en este artículo, el SDK de Azure para Java usa Netty de forma predeterminada para su transporte HTTP. Sin embargo, el SDK también proporciona un transporte HTTP conectable para que pueda usar otras implementaciones cuando corresponda. El SDK también proporciona dos implementaciones de transporte HTTP más para OkHttp y el cliente HTTP que se incluye con JDK 11 y versiones posteriores.

Directivas de canalización HTTP

Una canalización consta de una secuencia de pasos que se ejecutan para la ida y vuelta de cada solicitud-respuesta HTTP. Cada política tiene un propósito dedicado y actúa en una solicitud o una respuesta o, a veces, en ambas. Dado que todas las bibliotecas cliente tienen una capa estándar de "Azure Core", esta capa garantiza que cada directiva se ejecute en orden en la canalización. Al enviar una solicitud, las directivas se ejecutan en el orden en que son añadidas al flujo de trabajo. Cuando recibe una respuesta del servicio, las directivas se ejecutan en orden inverso. Todas las directivas agregadas a la canalización se ejecutan antes de enviar la solicitud y después de recibir una respuesta. La directiva tiene que decidir si actuar en la solicitud, la respuesta o ambas. Por ejemplo, una directiva de registro registra la solicitud y la respuesta, pero la directiva de autenticación solo está interesada en modificar la solicitud.

Azure Core Framework proporciona la directiva con los datos de solicitud y respuesta necesarios junto con cualquier contexto necesario para ejecutar la directiva. Después, la directiva puede realizar su operación con los datos especificados y pasar el control a la siguiente directiva de la canalización.

diagrama de canalización HTTP

Posición de la directiva de canalización HTTP

Al realizar solicitudes HTTP a servicios en la nube, es importante controlar los errores transitorios y reintentar los intentos con errores. Dado que esta funcionalidad es un requisito común, Azure Core proporciona una directiva de reintento que puede observar errores transitorios y reintentar automáticamente la solicitud.

Esta directiva de reintentos, por lo tanto, divide la canalización en dos partes: directivas que se ejecutan antes de la directiva de reintentos y directivas que se ejecutan después de la directiva de reintentos. Las directivas agregadas antes de la directiva de reintento se ejecutan solo una vez por operación de API, mientras que las directivas agregadas después de la directiva de reintento se ejecutan tantas veces como se realicen los reintentos.

Por lo tanto, al compilar la canalización HTTP, debe comprender si debe ejecutar una directiva para cada reintento de solicitud o una vez por operación de API.

Directivas comunes de canalización HTTP

Las canalizaciones HTTP para servicios basados en REST tienen configuraciones con directivas para la autenticación, reintentos, registro, telemetría y especificando el identificador de solicitud en el encabezado. Azure Core viene precargado con estas directivas HTTP comúnmente necesarias que puede agregar a la canalización.

Política Vínculo de GitHub
política de reintento RetryPolicy.java
directiva de autenticación BearerTokenAuthenticationPolicy.java
directiva de registro HttpLoggingPolicy.java
directiva de identificador de solicitud RequestIdPolicy.java
directiva de telemetría UserAgentPolicy.java

Directiva de canalización HTTP personalizada

La directiva de canalización HTTP proporciona un mecanismo práctico para modificar o decorar la solicitud y la respuesta. Puede agregar directivas personalizadas a la canalización que creó el usuario o el desarrollador de la biblioteca cliente. Al agregar la directiva a la canalización, puede especificar si esta directiva se debe ejecutar por llamada o por reintento.

Para crear una directiva de canalización HTTP personalizada, solo tiene que extender un tipo de directiva base e implementar algún método abstracto. Después, puede conectar la directiva a la canalización.

Encabezados personalizados en solicitudes HTTP

Las bibliotecas cliente del SDK de Azure para Java proporcionan una manera coherente de definir encabezados personalizados a través de objetos Context en la API pública, como se muestra en el ejemplo siguiente.

// 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 obtener más información, consulte la clase AddHeadersFromContextPolicy.

Biblioteca TLS/SSL predeterminada

Todas las bibliotecas cliente, de forma predeterminada, usan la biblioteca SSL de Boring nativa de Tomcat para habilitar el rendimiento de nivel nativo para las operaciones TLS/SSL. La biblioteca SSL boring es un archivo JAR uber que contiene bibliotecas nativas para Linux, macOS y Windows, y proporciona un mejor rendimiento en comparación con la implementación predeterminada de TLS/SSL dentro del JDK.

Reducir tamaño de dependencia Tomcat-Native TLS/SSL

De forma predeterminada, el uber JAR de la biblioteca Tomcat-Native Boring SSL se usa en los SDK de Azure para Java. Para reducir el tamaño de esta dependencia, debe incluirla con un clasificador os según netty-tcnative, como se muestra en el ejemplo siguiente.

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

Uso de TLS/SSL de JDK

Si prefiere usar el JDK TLS/SSL predeterminado en lugar de Tomcat-Native Boring SSL, entonces debe excluir la biblioteca nativa de Boring SSL de Tomcat. Tenga en cuenta que, en función de nuestras pruebas, el rendimiento de TLS/SSL de JDK es 30% más lento en comparación con Tomcat-Native BoringSSL. Cuando usa com.azure:azure-core:1.28.0 o posteriores, la biblioteca de implementación de HttpClient(por ejemplo, com.azure:azure-core-http-netty) administra la dependencia de Tomcat-Native Boring SSL. Para excluir la dependencia, agregue la siguiente configuración al archivo 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>

Pasos siguientes

Ahora que está familiarizado con la funcionalidad del cliente HTTP en El SDK de Azure para Java, aprenda a personalizar aún más el cliente HTTP que usa. Para más información, consulte Configurar proxies en Azure SDK para Java.