Prácticas recomendadas para el diseño y el desarrollo del proxy de API con Apigee

Esta página se aplica a Apigee y Apigee Hybrid.

Consulta la documentación de Apigee Edge.

En este documento, se proporciona un conjunto de prácticas recomendadas para desarrollar proxies de API con Apigee.

Entre los temas que se abordan aquí, se incluyen el diseño, la codificación, el uso de políticas, la supervisión y la depuración. La información se recopiló gracias a la experiencia de los desarrolladores que trabajan con Apigee para implementar programas de API exitosos. Este es un documento dinámico y se actualizará periódicamente.

Además de los lineamientos que se describen aquí, también te puede resultar útil la Introducción a los antipatrones.

Estándares de desarrollo

Comentarios y documentación

  • Proporciona comentarios intercalados en la configuración ProxyEndpoint y TargetEndpoint. Los comentarios mejoran la legibilidad de un flujo, en especial cuando los nombres de archivo de políticas no son lo suficientemente descriptivos para expresar la funcionalidad subyacente del flujo.
  • Haz que los comentarios sean útiles. Evita los comentarios evidentes.
  • Usa sangría coherente, espaciado, alineación vertical, etcétera.

Codificación del estilo de framework

La codificación de estilo del marco de trabajo implica almacenar los recursos del proxy de API en tu propio sistema de control de versiones para reutilizarlos en entornos de desarrollo locales. Por ejemplo, para reutilizar una política, almacénala en el control de código fuente, de modo que los desarrolladores puedan sincronizarse con ella y usarla en sus entornos de desarrollo de proxy.

  • Para habilitar DRY (una vez y solo una), siempre que sea posible, los parámetro de configuración y secuencias de comandos de políticas deben implementar funciones especializadas y reutilizables. Por ejemplo, una política exclusiva para extraer parámetros de búsqueda de mensajes de solicitud se podría llamar ExtractVariables.ExtractRequestParameters.
  • Limpia las políticas y los recursos que no se utilizan (JavaScript, Java, XSLT) de los proxies de API, en especial los recursos grandes que tienen el potencial de ralentizar los procedimientos de importación e implementación.

Convenciones de nombres

  • El atributo name de la política y el nombre del archivo de la política XML deben ser idénticos.
  • El atributo name de la política ServiceCallout y de secuencia de comandos, y el nombre del archivo de recursos deben ser idénticos.
  • DisplayName debe describir con precisión la función de la política a alguien que nunca haya trabajado con ese proxy de API.
  • Nombra las políticas según su función. Apigee recomienda que establezcas una convención de nombres coherente para tus políticas. Por ejemplo, usa prefijos cortos seguidos de una secuencia de palabras descriptivas separadas por guiones. Por ejemplo, AM-xxx para la política AssignMessage. Consulta también la herramienta de Apigeelint.
  • Usa las extensiones adecuadas para los archivos de recursos, .js para JavaScript, .py para Python y .jar para los archivos JAR de Java.
  • Los nombres de las variables deben ser coherentes. Si eliges un estilo, como CamelCase o under_score, úsalo en todo el proxy de API.
  • Cuando sea posible, usa prefijos de variables para organizar las variables según su propósito, por ejemplo, Consumer.username y Consumer.password.

Desarrollo del proxy de API

Consideraciones iniciales del diseño

  • Para obtener orientación sobre el diseño de la API de RESTful, descarga el libro electrónico Diseño de la API web: el vínculo faltante.
  • Aprovecha las políticas y la funcionalidad de Apigee siempre que sea posible para compilar proxies de API. Evita codificar toda la lógica de proxy en los recursos de JavaScript, Java o Python.
  • Construye flujos de una manera organizada. Es preferible usar varios flujos, cada uno con una sola condición, en lugar de varios adjuntos condicionales en el mismo flujo previo y posterior.
  • Como "modo a prueba de fallas", crea un proxy de API predeterminado con un ProxyEndpointEndpoint basePath de /. Esto se puede usar para redireccionar las solicitudes a la API base a un sitio de desarrollador, a fin de mostrar una respuesta personalizada o realizar otra acción más útil que mostrar el messaging.adaptors.http.flow.ApplicationNotFound predeterminado.
  • Para obtener un rendimiento óptimo, Apigee recomienda usar no más de 3,000 rutas de acceso de proxy de API por entorno o grupo de entornos de Apigee. Superar esta recomendación puede aumentar la latencia de todas las implementaciones de proxy de APIs nuevas y existentes.
  • Usa los recursos de TargetServer para separar los parámetros de configuración de TargetEndpoint de URLs concretas, lo cual admite la promoción en todos los entornos.
    Consulta Balanceo de cargas entre servidores de backend.
  • Si tienes varias RouteRules, crea una como predeterminada, es decir, como una RouteRule sin condición. Asegúrate de que la RouteRule predeterminada esté definida al final de la lista de rutas condicionales. Las RouteRules se evalúan de forma vertical en ProxyEndpoint. Consulta la referencia de configuración de proxy de API.
  • Tamaño del paquete de proxy de API: Los paquetes de proxy de API no pueden superar los 15 MB.
  • Control de versiones de API: Para obtener las ideas y recomendaciones de Apigee sobre el control de versiones de API, consulta Control de versiones en el libro electrónico Web API Design: The Missing Link.

Habilita CORS

Antes de publicar tus API, deberás agregar la política de CORS al flujo previo de solicitud de ProxyEndpoint para admitir solicitudes de origen cruzado del cliente.

CORS (uso compartido de recursos entre dominios) es un mecanismo estándar que permite que las llamadas XMLHttpRequest (XHR) de JavaScript que se ejecutan en una página web interactúen con recursos de dominios que no son de origen, CORS es una solución implementada con frecuencia en la política del mismo origen que aplican todos los navegadores. Por ejemplo, si realizas una llamada XHR a la API de Twitter desde el código JavaScript que se ejecuta en tu navegador, la llamada fallará. Esto se debe a que el dominio que entrega la página a tu navegador no es el mismo que el dominio que entrega la API de Twitter. CORS proporciona una solución a este problema, ya que permite que los servidores habiliten si desean proporcionar uso compartido de recursos entre dominios.

Para obtener información sobre cómo habilitar CORS en los proxies de API antes de publicar las API, consulta Cómo agregar compatibilidad con CORS a un proxy de API.

Tamaño de la carga útil del mensaje

Para evitar problemas de memoria en Apigee, el tamaño de la carga útil del mensaje está restringido a 10 MB. Si se exceden esos tamaños, se generará un error protocol.http.TooBigBody.

Este problema también se analiza en Error al solicitar o mostrar una carga útil de gran tamaño con el proxy de Apigee.

A continuación, se detallan las estrategias recomendadas para controlar tamaños de mensajes grandes en Apigee:

Control de fallas

  • Se pueden usar FaultRules para controlar todas las fallas. (Las políticas RaiseFault se usan para detener el flujo de mensajes y enviar el procesamiento al flujo FaultRules).
  • Dentro del flujo FaultRules, usa una política AssignMessage para compilar la respuesta de falla, no una política RaiseFault. Ejecuta condicionalmente políticas AssignMessage en función del tipo de falla que ocurra.
  • Siempre incluye un controlador de fallas "catch-all" predeterminado para que las fallas generadas por el sistema se puedan asignar a formatos de respuesta de fallas definidos por el cliente.
  • Si es posible, haz que las respuestas de fallas siempre coincidan con cualquier formato estándar disponible en tu empresa o proyecto.
  • Usa mensajes de error significativos y legibles que sugieran una solución a la condición de error.

Consulta Controla errores.

Persistencia

Mapas clave-valor

  • Usa mapas de clave-valor solo para conjuntos de datos limitados. No están diseñados como un almacén de datos a largo plazo.
  • Ten en cuenta el rendimiento cuando uses mapas de clave-valor, ya que esta información se almacena en la base de datos de Cassandra.

Consulta la política KeyValueMapOperations.

Almacenamiento en caché de respuesta

  • No propagues la caché de respuesta si la respuesta no tiene éxito o si la solicitud no es una GET. Las operaciones de creación, actualización y eliminación no se deben almacenar en caché. <SkipCachePopulation>response.status.code != 200 or request.verb != "GET"</SkipCachePopulation>
  • Propaga la caché con un solo tipo de contenido coherente (por ejemplo, XML o JSON). Después de recuperar una entrada responseCache y, luego, convertirla al tipo de contenido necesario con JSONtoXML o XMLToJSON. Esto evitará almacenar dos, tres o más datos.
  • Asegúrate de que la clave de caché sea suficiente para cumplir con el requisito de almacenamiento en caché. En muchos casos, request.querystring se puede usar como identificador único.
  • No incluyas la clave de API (client_id) en la clave de caché, a menos que se requiera de forma explícita. Por lo general, las API protegidas solo por una clave mostrarán los mismos datos a todos los clientes para una solicitud determinada. No es eficiente almacenar el mismo valor para una cantidad de entradas basadas en la clave de API.
  • Establece intervalos de vencimiento de caché adecuados para evitar lecturas no confirmadas.
  • Siempre que sea posible, intenta que la política de caché de respuesta que propaga la caché se ejecute en el flujo de respuesta ProxyEndpoint lo más tarde posible. En otras palabras, haz que se ejecute después de los pasos de traducción y mediación, incluida la encriptación basada en JavaScript y la conversión entre JSON y XML. Si almacenas en caché los datos mediados, evitarás el costo de rendimiento que implica ejecutar el paso de mediación cada vez que recuperas datos almacenados en caché.

    Ten en cuenta que tal vez quieras almacenar en caché datos sin mediación si la mediación da como resultado una respuesta diferente de una solicitud a otra.

  • La política de caché de respuesta para buscar la entrada de caché debe ocurrir en la solicitud PreFlow de ProxyEndpoint. Evita implementar demasiada lógica, distinta de la generación de claves de caché, antes de mostrar una entrada de caché. De lo contrario, se minimizan los beneficios del almacenamiento en caché.
  • En general, debes mantener siempre la búsqueda de caché de respuesta lo más cerca posible de la solicitud del cliente. Por el contrario, debes conservar la población de caché de respuesta lo más cerca posible de la respuesta del cliente.
  • Cuando uses varias políticas de caché de respuesta diferentes en un proxy, sigue estos lineamientos a fin de garantizar un comportamiento discreto para cada uno:
    • Ejecuta cada política en función de condiciones mutuamente excluyentes. Esto ayudará a garantizar que solo se ejecute una de las políticas de caché de respuesta múltiple.
    • Define diferentes recursos de caché para cada política de caché de respuesta. Debes especificar el recurso de caché en el elemento <CacheResource> de la política.

Consulta la política ResponseCache.

Política y código personalizado

¿Deseas un código personalizado o una política?

  • Usa las políticas integradas en primer lugar (siempre que sea posible). Las políticas de Apigee se endurecen, optimizan y admiten. Por ejemplo, usa las políticas estándar AssignMessage y ExtractVariables en lugar de JavaScript (cuando sea posible) para crear cargas útiles, extraer información de las cargas útiles (XPath, JSONPath), etcétera.
  • Se prefiere JavaScript en lugar de Python y Java. Sin embargo, si el rendimiento es el requisito principal, Java debe usarse en JavaScript.

JavaScript

  • Usa JavaScript si es más intuitivo que las políticas de Apigee (por ejemplo, cuando configuras target.url para muchas combinaciones de URI diferentes).
  • Análisis de carga útil compleja, como iteración mediante un objeto JSON y codificación/decodificación de Base64.
  • La política JavaScript tiene un límite de tiempo, por lo que se pueden bloquear bucles infinitos.
  • Usa siempre los pasos de JavaScript y coloca los archivos en la carpeta de recursos jsc. El tipo de política JavaScript precompila el código en el momento de la implementación.

Java

  • Usa Java si el rendimiento es la mayor prioridad o si la lógica no se puede implementar en JavaScript.
  • Incluye archivos fuente de Java en el seguimiento del código fuente.

Consulta la política JavaCallout para obtener información sobre el uso de Java en proxies de API.

Python

  • No uses Python, a menos que sea absolutamente obligatorio. Las secuencias de comandos de Python pueden generar cuellos de botella en el rendimiento de ejecuciones simples, ya que se interpreta en el entorno de ejecución.

Texto destacado en secuencias de comandos (Java, JavaScript, Python)

  • Usa un try-catch global o equivalente.
  • Genera excepciones significativas y capturalas correctamente para usarlas en respuestas a fallas.
  • Genera y detecta las excepciones con anticipación. No uses el try-catch global para controlar todas las excepciones.
  • Realiza verificaciones nulas y no definidas cuando sea necesario. Un ejemplo de cuándo hacer esto es cuando se recuperan variables de flujo opcionales.
  • Evita realizar solicitudes HTTP/S dentro de un texto destacado de la secuencia de comandos. En su lugar, usa la política ServiceCallout, ya que la política controla las conexiones con facilidad.

JavaScript

  • JavaScript en la plataforma de API es compatible con XML a través de E4X.

Consulta el modelo de objetos de JavaScript.

Java

  • Cuando accedas a las cargas útiles de mensajes, intenta usar context.getMessage() en comparación con context.getResponseMessage o context.getRequestMessage. Esto garantiza que el código pueda recuperar la carga útil, tanto en los flujos de solicitud como en los de respuesta.
  • Importa bibliotecas al entorno o a la organización de Apigee y no las incluyas en el archivo JAR. Esto reduce el tamaño del paquete y permitirá que otros archivos JAR accedan al mismo repositorio de biblioteca.
  • Importa los archivos JAR con la API de recursos de Apigee en lugar de incluirlos en la carpeta de recursos del proxy de API. Esto reducirá los tiempos de implementación y permitirá que varios proxies de API hagan referencia a los mismos archivos JAR. Otro beneficio es el aislamiento del cargador de clase.
  • No uses Java para manejar recursos (por ejemplo, crear y administrar grupos de subprocesos).

Python

  • Genera excepciones significativas y detéctalas correctamente para usarlas en respuestas a fallas de Apigee.

Consulta la política PythonScript.

ServiceCallouts

  • Hay muchos casos de uso válidos para usar encadenamiento de proxy, en los que usas un texto destacado de servicio en un proxy de API para llamar a otro proxy de API. Si usas el encadenamiento de proxy, asegúrate de evitar los textos destacados recurrentes de bucle infinito en el mismo proxy de API.

    Si te conectas entre proxies que están en la misma organización y entorno, asegúrate de consultar Encadena proxies de API para obtener más información sobre la implementación de una conexión local que evite la sobrecarga innecesaria de la red.

  • Compila un mensaje de solicitud ServiceCallout mediante la política AssignMessage y propaga el objeto de solicitud en una variable de mensaje. Esto incluye configurar la carga útil, la ruta y el método de la solicitud.
  • La URL que se configura dentro de la política requiere la especificación del protocolo, es decir, la parte del protocolo de la URL; por ejemplo, https:// no se puede especificar mediante una variable. Además, debes usar variables separadas para la parte del dominio de la URL y el resto de la URL. Por ejemplo: https://example.com.
  • Almacena el objeto de respuesta para un ServiceCallout en una variable de mensaje separada. Luego, puedes analizar la variable de mensaje y mantener intacta la carga útil original del mensaje para que la usen otras políticas.

Consulta Política de ServiceCallout.

Accede a entidades

Política AccessEntity

  • Para mejorar el rendimiento, busca apps por uuid en lugar del nombre de la app.

Consulta la política AccessEntity.

Logging

  • Usa una política syslog común en conjuntos y dentro del mismo paquete. Esto mantendrá un formato de registro coherente.

Consulta la política MessageLogging.

Supervisión

No es necesario que los clientes de Cloud verifiquen componentes individuales de Apigee (routers, procesadores de mensajes, etcétera). El equipo de operaciones globales de Apigee está supervisando de forma exhaustiva todos los componentes, junto con las verificaciones de estado de la API, dadas las solicitudes de verificación de estado del cliente.

Estadísticas de Apigee

Las estadísticas puede proporcionar supervisión de API no críticas a medida que se miden los porcentajes de error.

Consulta los paneles de control de Analytics.

Depurar

La herramienta de seguimiento en la IU de Apigee es útil para depurar problemas de la API del entorno de ejecución durante la operación de desarrollo o producción de una API.

Consulta Usa la herramienta de depuración.

Seguridad

Lógica personalizada en proxies de API

Un requisito común cuando se compilan proxies de API es incluir lógica para procesar solicitudes o respuestas. Si bien muchos requisitos se pueden cumplir desde un conjunto predefinido de pasos, acciones o políticas, como verificar un token, aplicar una cuota o responder con un objeto almacenado en caché, a menudo se puede requerir acceso a la programación. Por ejemplo, buscar una ubicación (extremo) desde una tabla de enrutamiento basada en una clave encontrada en una solicitud y aplicar de forma dinámica un extremo de destino o un método de autenticación personalizado o de propiedad, etcétera.

Apigee proporciona al desarrollador varias opciones para abordar esa lógica personalizada. En este documento, se explorarán estas opciones y cuándo se podrá usar cada una de ellas:

Política Casos de uso de políticas
JavaScript y PythonScript

Cuándo usarla:

  • Las políticas de JavaScript y PythonScript son equivalentes en cuanto a su capacidad. La familiaridad de un desarrollador con un lenguaje suele ser la motivación para elegir uno sobre otro.
  • Las políticas de JavaScript y PythonScript son más adecuadas para procesar la lógica intercalada que no es demasiado compleja y no requiere el uso de bibliotecas de terceros.
  • Estas políticas no son tan eficaces como la política de JavaCallout.

Cuándo no se debería usar:

  • La puerta de enlace de API de Apigee no es un servidor de aplicaciones (ni proporciona el entorno de ejecución completo de JavaScript como node.js). Si el texto destacado siempre toma más de un segundo en procesarse, es probable que la lógica no pertenezca a la puerta de enlace y, en cambio, debería ser parte del servicio subyacente.

Práctica recomendada: Apigee recomienda JavaScript en lugar de PythonScript, ya que JavaScript ofrece un mejor rendimiento.

JavaCallout

Cuándo usarla:

  • El rendimiento del procesamiento de la lógica intercalado es fundamental.
  • Las bibliotecas de Java existentes proporcionan gran parte de la lógica.

Cuándo no se debería usar:

  • La puerta de enlace de API de Apigee no es un servidor de aplicaciones y no está diseñado para cargar frameworks como Spring, JEE, etc. Si el texto destacado suele demorar más de un segundo en procesarse, la lógica se puede considerar funcional (lógica empresarial). Considera externalizarte como servicio.
  • Para proteger la puerta de enlace de API de Apigee contra el abuso, se aplican restricciones al tipo de código que se puede ejecutar. Por ejemplo, el código Java que intenta acceder a ciertas bibliotecas criptográficas o acceder al sistema de archivos está bloqueado para la ejecución.
  • Las aplicaciones de Java, en particular aquellas que dependen de bibliotecas de terceros, pueden incorporar muchos archivos JAR (y grandes). Estas pueden ralentizar el tiempo de inicio de las puertas de enlace.
ExternalCallout

Cuándo usarla:

  • Lo ideal es externalizar la lógica personalizada y permitir que esta acceda al contexto de mensajes (y, si es necesario, modificarlo).
  • Los textos destacados externos implementan gRPC y pueden tener un mejor rendimiento que un ServiceCallout.
  • Cuando uses Apigee o Apigee Hybrid en Google Cloud, considera usar Cloud Functions o Cloud Run para alojar esa lógica.
  • Como reemplazo efectivo para la característica de Destinos alojados en Apigee Edge.

Cuando no se debería usar:

  • Para obtener una lógica básica que pueda ejecutarse con rapidez y de forma intercalada.
ServiceCallout

Cuándo usarla:

  • La lógica compleja se implementa mejor fuera de la puerta de enlace. Esta lógica puede tener su propio ciclo de vida (versiones y control de versiones) y no afecta el funcionamiento de la puerta de enlace.
  • Cuando el extremo REST/SOAP/GraphQL ya existe o se puede implementar fácilmente
  • Cuando uses Apigee o Apigee Hybrid en Google Cloud, considera usar Cloud Functions o Cloud Run para alojar esa lógica.
  • Como reemplazo efectivo para la característica de Destinos alojados en Apigee Edge.

Cuando no se debería usar:

  • Para obtener una lógica liviana que se pueda ejecutar con rapidez y de forma intercalada
  • El proxy de API debe transferir el contexto (como las variables) o recibir el contexto de la implementación externa

En síntesis:

  1. Si la lógica es simple o trivial, usa JavaScript (preferentemente) o PythonScript.
  2. Si la lógica intercalada requiere un mejor rendimiento que JavaScript o PythonScript, usa JavaCallout.
  3. Si la lógica debe externalizarse, utiliza ExternalCallout.
  4. Si ya tienes implementaciones externas o desarrolladores que están familiarizados con REST, usa ServiceCallout.

En la siguiente figura, se ilustra este proceso: