Prácticas recomendadas para diseñar y desarrollar proxies 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 describen una serie de prácticas recomendadas para desarrollar proxies de API con Apigee.

Entre los temas que se tratan aquí se incluyen el diseño, la codificación, el uso de políticas, la monitorización y la depuración. La información se ha recogido a partir de la experiencia de los desarrolladores que han trabajado con Apigee para implementar programas de APIs eficaces. Este documento está abierto a modificaciones y se actualizará periódicamente.

Además de las directrices que se indican en este artículo, puede resultarte útil consultar la introducción a los antipatrones.

Estándares de desarrollo

Comentarios y documentación

  • Añade comentarios entre líneas en las configuraciones ProxyEndpoint y TargetEndpoint. Los comentarios mejoran la legibilidad de un flujo, sobre todo cuando los nombres de los archivos de políticas no son lo suficientemente descriptivos como para expresar la funcionalidad subyacente del flujo.
  • Escribe comentarios útiles. Evita los comentarios obvios.
  • Usa una sangría, un espaciado y una alineación vertical coherentes, entre otros.

Codificación de estilo de framework

La codificación de estilo de framework implica almacenar recursos de proxy de API en tu propio sistema de control de versiones para reutilizarlos en diferentes entornos de desarrollo locales. Por ejemplo, para reutilizar una política, guárdala en un control de origen para que los desarrolladores puedan sincronizarla y usarla en sus propios entornos de desarrollo de proxies.

  • Para habilitar DRY (no te repitas), siempre que sea posible, las configuraciones de políticas y las secuencias de comandos deben implementar funciones especializadas y reutilizables. Por ejemplo, una política específica para extraer parámetros de consulta de mensajes de solicitud podría llamarse ExtractVariables.ExtractRequestParameters.
  • Elimina las políticas y los recursos sin usar (JavaScript, Java, XSLT, etc.) de los proxies de API, especialmente los recursos de gran tamaño que pueden 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 política XML deben ser idénticos.
  • El atributo name de las políticas Script y ServiceCallout 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.
  • Asigna nombres a las políticas en función de su función. Apigee recomienda que establezcas una convención de nomenclatura 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 apigeelint.
  • Usa las extensiones adecuadas para los archivos de recursos: .js para JavaScript, .py para Python y .jar para 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.
  • Utiliza prefijos de variables, siempre que sea posible, para organizar las variables según su finalidad. Por ejemplo, Consumer.username y Consumer.password.

Desarrollo de proxies de API

Consideraciones iniciales sobre el diseño

  • Para obtener información sobre el diseño de APIs RESTful, descarga el libro electrónico Web API Design: The Missing Link.
  • Aprovecha las políticas y las funciones de Apigee siempre que sea posible para crear proxies de API. Evita codificar toda la lógica del proxy en recursos de JavaScript, Java o Python.
  • Crea flujos de forma organizada. Es preferible usar varios flujos, cada uno con una sola condición, que usar varios adjuntos condicionales en el mismo PreFlow y PostFlow.
  • Como medida de seguridad, crea un proxy de API predeterminado con un BasePath de ProxyEndpoint de /. Se puede usar para redirigir solicitudes de la API base a un sitio de desarrolladores, devolver una respuesta personalizada o realizar otra acción más útil que devolver el valor predeterminado messaging.adaptors.http.flow.ApplicationNotFound.
  • Para obtener un rendimiento óptimo, Apigee recomienda usar un máximo de 3000 rutas base de proxy de API por entorno o grupo de entornos de Apigee. Si superas esta recomendación, puede aumentar la latencia de todos los despliegues de proxy de API nuevos y actuales.
  • Usa recursos TargetServer para desacoplar las configuraciones de TargetEndpoint de URLs concretas, lo que permite promocionar en diferentes entornos.
    Consulta Balanceo de carga en servidores de backend.
  • Si tienes varias RouteRules, crea una como "predeterminada", es decir, como una RouteRule sin ninguna condición. Asegúrate de que RouteRule predeterminado se defina en último lugar en la lista de rutas condicionales. Las RouteRules se evalúan de arriba abajo en ProxyEndpoint. Consulta la referencia de configuración de proxies de APIs.
  • Tamaño del paquete de proxy de API: los paquetes de proxy de API no pueden superar los 15 MB.
  • Control de versiones de APIs: para conocer las opiniones y recomendaciones de Apigee sobre el control de versiones de APIs, consulta Versioning (Control de versiones) en el libro electrónico Web API Design: The Missing Link (Diseño de APIs web: el eslabón perdido).

Habilitar CORS

Antes de publicar tus APIs, debes añadir la política CORS al PreFlow de la solicitud de ProxyEndpoint para admitir solicitudes entre orígenes del lado del cliente.

CORS (uso compartido de recursos entre dominios) es un mecanismo estándar que permite que las llamadas XMLHttpRequest (XHR) de JavaScript ejecutadas en una página web interactúen con recursos de dominios que no son de origen. CORS es una solución que se implementa habitualmente para la política de coincidencia de origen que aplican todos los navegadores. Por ejemplo, si haces una llamada XHR a la API de Twitter desde código JavaScript que se ejecuta en tu navegador, la llamada fallará. Esto se debe a que el dominio que sirve la página a tu navegador no es el mismo que el que sirve la API de Twitter. CORS ofrece una solución a este problema, ya que permite que los servidores habiliten la opción si quieren ofrecer el uso compartido de recursos entre dominios.

Para obtener información sobre cómo habilitar CORS en tus proxies de APIs antes de publicar las APIs, consulta Añadir compatibilidad con CORS a un proxy de APIs.

Tamaño de la carga útil del mensaje

El tamaño de la carga útil de los mensajes en los flujos de solicitudes o respuestas de Apigee está limitado de forma predeterminada a 10 MB. Los usuarios que necesiten procesar cargas útiles grandes pueden configurar un límite superior mediante el elemento <Properties> en las configuraciones ProxyEndpoint o TargetEndpoint de sus proxies de API.

Para obtener más información sobre cómo usar response.payload.parse.limit o las propiedades request.payload.parse.limit para configurar un tamaño máximo de carga útil de hasta 30 MB para los flujos de solicitudes o respuestas, consulta la referencia de configuración de proxy de API.

Ten en cuenta que, si se supera el tamaño de mensaje especificado, se producirá un error protocol.http.TooBigBody.

Estas son algunas estrategias recomendadas para gestionar tamaños de mensajes grandes en Apigee:

  • Te recomendamos que aísles las proxies de API que gestionan cargas útiles grandes con frecuencia en un entorno dedicado para evitar posibles problemas de "vecino ruidoso". Los recursos de CPU y memoria del sistema se consumen en mayor cantidad por los proxies que gestionan cargas útiles grandes, sobre todo cuando se usan junto con políticas que interactúan con cargas útiles grandes.
  • También recomendamos limitar el uso de políticas para interactuar con cargas útiles grandes. Usar políticas para analizar y copiar repetidamente las cargas útiles de solicitudes o respuestas puede afectar negativamente al rendimiento del sistema.
  • Recomendamos a las organizaciones que gestionen grandes volúmenes de solicitudes de carga útil elevada que proporcionen direcciones IP adicionales para evitar el agotamiento de puertos debido al escalado horizontal.
  • Ten en cuenta las solicitudes y respuestas de streaming. Ten en cuenta que, cuando transmitas contenido, las políticas ya no tendrán acceso al contenido de los mensajes. Consulta Solicitudes y respuestas de streaming.
  • Si tu organización usa la facturación por uso, te recomendamos que uses los límites configurables para cargas útiles grandes solo en los proxies de API implementados en el entorno Comprehensive.

Gestión de errores

  • Aprovecha FaultRules para gestionar todos los errores. (Las políticas RaiseFault se usan para detener el flujo de mensajes y enviar el procesamiento al flujo FaultRules).
  • En el flujo FaultRules, usa una política AssignMessage para crear la respuesta de error, no una política RaiseFault. Ejecuta de forma condicional las políticas AssignMessage en función del tipo de error que se produzca.
  • Siempre incluye un controlador de errores predeterminado para que los errores generados por el sistema se puedan asignar a formatos de respuesta de errores definidos por el cliente.
  • Si es posible, haz que las respuestas de error coincidan con los formatos estándar disponibles en tu empresa o proyecto.
  • Usa mensajes de error significativos y legibles que sugieran una solución al error.

Consulta Gestionar fallos.

Persistencia

Mapas de clave-valor

  • Utilice mapas de clave-valor solo para conjuntos de datos limitados. No están diseñados para ser un almacén de datos a largo plazo.
  • Tenga en cuenta el rendimiento al usar 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 respuestas

  • No rellene la caché de respuestas si la respuesta no es correcta o si la solicitud no es una solicitud GET. Las creaciones, actualizaciones y eliminaciones no se deben almacenar en caché. <SkipCachePopulation>response.status.code != 200 or request.verb != "GET"</SkipCachePopulation>
  • Rellena la caché con un solo tipo de contenido coherente (por ejemplo, XML o JSON). Después de recuperar una entrada de responseCache, conviértela al tipo de contenido necesario con JSONtoXML o XMLToJSON. De esta forma, se evitará que se almacenen datos duplicados, triplicados o más.
  • Asegúrate de que la clave de caché sea suficiente para el requisito de almacenamiento en caché. En muchos casos, el request.querystring se puede usar como identificador único.
  • No incluyas la clave de API (client_id) en la clave de caché, a menos que sea necesario. En la mayoría de los casos, las APIs protegidas solo con una clave devolverán los mismos datos a todos los clientes para una solicitud determinada. No es eficiente almacenar el mismo valor para varias entradas en función de la clave de API.
  • Define intervalos de vencimiento de caché adecuados para evitar lecturas sucias.
  • Siempre que sea posible, intenta que la política de caché de respuestas que rellena la caché se ejecute en el PostFlow de la respuesta ProxyEndpoint lo más tarde posible. Es decir, que se ejecute después de los pasos de traducción y mediación, incluidos los de mediación basada en JavaScript y conversión entre JSON y XML. Al almacenar en caché los datos mediados, evitas el coste de rendimiento de ejecutar el paso de mediación cada vez que recuperas datos almacenados en caché.

    Ten en cuenta que, en su lugar, puede que te interese almacenar en caché los 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 respuestas para buscar la entrada de caché debe producirse en el PreFlow de la solicitud ProxyEndpoint. Evita implementar demasiada lógica, aparte de la generación de claves de caché, antes de devolver una entrada de caché. De lo contrario, las ventajas del almacenamiento en caché se minimizan.
  • En general, siempre debes mantener la búsqueda en la caché de respuestas lo más cerca posible de la solicitud del cliente. Por el contrario, debes mantener la población de la caché de respuestas lo más cerca posible de la respuesta del cliente.
  • Cuando uses varias políticas de caché de respuestas diferentes en un proxy, sigue estas directrices para asegurarte de que cada una tenga un comportamiento independiente:
    • Ejecuta cada política en función de condiciones mutuamente excluyentes. De esta forma, se asegura de que solo se ejecute una de las varias políticas de caché de respuestas.
    • Define diferentes recursos de caché para cada política de caché de respuestas. Especifica el recurso de caché en el elemento <CacheResource> de la política.

Consulta la política ResponseCache.

Política y código personalizado

¿Política o código personalizado?

  • Utiliza las políticas integradas en primer lugar (siempre que sea posible). Las políticas de Apigee están reforzadas, optimizadas y admitidas. 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 cargas útiles (XPath, JSONPath), etc.
  • Se prefiere JavaScript a Python y Java. Sin embargo, si el rendimiento es el requisito principal, se debe usar Java en lugar de JavaScript.

JavaScript

  • Usa JavaScript si te resulta más intuitivo que las políticas de Apigee (por ejemplo, al definir target.url para muchas combinaciones de URIs diferentes).
  • Análisis de cargas útiles complejas, como iterar en un objeto JSON y codificar o decodificar en Base64.
  • La política de JavaScript tiene un límite de tiempo, por lo que los bucles infinitos se bloquean.
  • Usa siempre pasos de JavaScript y coloca los archivos en la carpeta jsc resources. El tipo de política de JavaScript precompila el código en el momento de la implementación.

Java

  • Usa Java si el rendimiento es la prioridad más alta 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 cómo usar Java en proxies de API.

Python

  • No uses Python a menos que sea absolutamente necesario. Las secuencias de comandos de Python pueden provocar cuellos de botella en el rendimiento en ejecuciones sencillas, ya que se interpretan en tiempo de ejecución.

Llamadas a secuencias de comandos (Java, JavaScript y Python)

  • Usa un bloque try/catch global o equivalente.
  • Lanza excepciones significativas y captúralas correctamente para usarlas en las respuestas de error.
  • Lanza y detecta excepciones pronto. No uses el bloque try/catch global para gestionar todas las excepciones.
  • Realiza comprobaciones de valores nulos e indefinidos cuando sea necesario. Por ejemplo, cuando se recuperan variables de flujo opcionales.
  • No hagas solicitudes HTTP/S dentro de una llamada de script. En su lugar, utilice la política ServiceCallout, ya que esta gestiona las conexiones correctamente.

JavaScript

  • JavaScript en la plataforma de APIs admite XML a través de E4X.

Consulta el modelo de objetos de JavaScript.

Java

  • Cuando accedas a las cargas útiles de los mensajes, intenta usar context.getMessage() en lugar de context.getResponseMessage o context.getRequestMessage. De esta forma, el código puede recuperar la carga útil tanto en los flujos de solicitudes como en los de respuestas.
  • Importa bibliotecas a la organización o al entorno de Apigee y no las incluyas en el archivo JAR. De esta forma, se reduce el tamaño del paquete y otros archivos JAR podrán acceder al mismo repositorio de bibliotecas.
  • Importa archivos JAR con la API de recursos de Apigee en lugar de incluirlos en la carpeta de recursos del proxy de API. De esta forma, se reducirán los tiempos de implementación y se permitirá que varios proxies de API hagan referencia a los mismos archivos JAR. Otra ventaja es el aislamiento del cargador de clases.
  • No uses Java para gestionar recursos (por ejemplo, para crear y gestionar grupos de subprocesos).

Python

  • Genera excepciones significativas y captúralas correctamente para usarlas en las respuestas de errores de Apigee

Consulta la política de PythonScript.

ServiceCallouts

  • Hay muchos casos prácticos válidos para usar el encadenamiento de proxies, en los que se usa una llamada de servicio en un proxy de API para llamar a otro proxy de API. Si usas el encadenamiento de proxies, asegúrate de evitar las llamadas recursivas de bucle infinito al mismo proxy de API.

    Si vas a conectar proxies que están en la misma organización y entorno, consulta Encadenar proxies de API para obtener más información sobre cómo implementar una conexión local que evite una sobrecarga de red innecesaria.

  • Crea un mensaje de solicitud ServiceCallout con la política AssignMessage y rellena el objeto de solicitud en una variable de mensaje. Esto incluye definir la carga útil, la ruta y el método de la solicitud.
  • La URL configurada en la política requiere la especificación del protocolo, lo que significa que la parte del protocolo de la URL (por ejemplo, https://) no se puede especificar mediante una variable. Además, debe usar variables independientes para la parte del dominio de la URL y para el resto de la URL. Por ejemplo: https://example.com.
  • Almacena el objeto de respuesta de un ServiceCallout en una variable de mensaje independiente. A continuación, puedes analizar la variable del mensaje y mantener intacta la carga útil del mensaje original para que la usen otras políticas.

Consulta la política ServiceCallout.

Acceder a entidades

Política de AccessEntity

  • Para obtener un mejor rendimiento, busca aplicaciones por uuid en lugar de por el nombre de la aplicación.

Consulta la política AccessEntity.

Almacenamiento de registros

  • Usa una política de syslog común en todos los paquetes y dentro del mismo paquete. De esta forma, se mantendrá un formato de registro coherente.

Consulta la política MessageLogging.

Supervisión

Los clientes de Cloud no tienen que comprobar los componentes individuales de Apigee (routers, procesadores de mensajes, etc.). El equipo de Operaciones Globales de Apigee monitoriza exhaustivamente todos los componentes, así como las comprobaciones del estado de las APIs, en función de las solicitudes de comprobación del estado que envían los clientes.

Apigee Analytics

Analytics puede proporcionar una monitorización de la API no crítica, ya que se miden los porcentajes de errores.

Consulta Paneles de control de Analytics.

Depurar

La herramienta de seguimiento de la interfaz de usuario de Apigee es útil para depurar problemas de la API en tiempo de ejecución durante el desarrollo o la operación de producción de una API.

Consulta Usar la herramienta de depuración.

Seguridad

Lógica personalizada en proxies de API

Un requisito habitual al crear proxies de API es incluir cierta lógica para procesar solicitudes o respuestas. Aunque muchos requisitos se pueden cumplir con 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 requiere acceso a la programabilidad. Por ejemplo, buscar una ubicación (endpoint) en una tabla de enrutamiento en función de una clave encontrada en una solicitud y aplicar dinámicamente un endpoint de destino o un método de autenticación personalizado o propietario, etc.

Apigee ofrece a los desarrolladores varias opciones para gestionar esta lógica personalizada. En este documento se analizarán esas opciones y se explicará cuándo usar cada una:

Política Casos prácticos de políticas
JavaScript y PythonScript

Cuándo debe usarse:

  • Las políticas JavaScript y PythonScript tienen las mismas funciones. La familiaridad de un desarrollador con un lenguaje suele ser el motivo por el que elige uno u otro.
  • Las políticas de JavaScript y PythonScript son las más adecuadas para procesar la lógica en línea que no sea demasiado compleja y no requiera el uso de bibliotecas de terceros.
  • Estas políticas no tienen el mismo rendimiento que la política JavaCallout.

Cuándo no se deben utilizar:

  • La pasarela de APIs de Apigee no es un servidor de aplicaciones (ni proporciona el tiempo de ejecución completo de JavaScript como node.js). Si la llamada siempre tarda más de un segundo en procesarse, lo más probable es que la lógica no pertenezca a la pasarela y deba formar parte del servicio subyacente.

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

JavaCallout

Cuándo debe usarse:

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

Cuándo no se deben utilizar:

  • La pasarela de APIs de Apigee no es un servidor de aplicaciones y no está diseñada para cargar frameworks como Spring o JEE, entre otros. Si la llamada tarda más de un segundo en procesarse, la lógica se puede considerar funcional (lógica empresarial). Plantéate externalizarlo como servicio.
  • Para proteger la pasarela de API de Apigee frente a usos inadecuados, se han aplicado restricciones al tipo de código que se puede ejecutar. Por ejemplo, se bloquea la ejecución del código Java que intenta acceder a determinadas bibliotecas criptográficas o al sistema de archivos.
  • Las aplicaciones Java, especialmente las que dependen de bibliotecas de terceros, pueden incluir muchos archivos JAR (de gran tamaño). Esto puede ralentizar el tiempo de arranque de las pasarelas.
ExternalCallout

Cuándo debe usarse:

  • Es ideal para externalizar la lógica personalizada y permitir que esta acceda (y, si es necesario, modifique) el contexto del mensaje.
  • Las llamadas externas implementan gRPC y pueden tener un mejor rendimiento que un ServiceCallout.
  • Si usas Apigee o Apigee hybrid en Google Cloud, te recomendamos que uses Cloud Functions o Cloud Run para alojar esa lógica.
  • Como sustituto eficaz de la función Hosted Targets de Apigee Edge.

Cuándo no se debe usar:

  • Para una lógica ligera que se pueda ejecutar rápidamente, en línea.
ServiceCallout

Cuándo debe usarse:

  • Es mejor implementar la lógica compleja fuera de la pasarela. Esta lógica puede tener su propio ciclo de vida (lanzamientos y versiones) y no afecta al funcionamiento de la pasarela.
  • Cuando el endpoint REST, SOAP o GraphQL ya existe o se puede implementar fácilmente
  • Si usas Apigee o Apigee Hybrid en Google Cloud, te recomendamos que uses Cloud Functions o Cloud Run para alojar esa lógica.
  • Como sustituto eficaz de la función Hosted Targets de Apigee Edge.

Cuándo no se debe usar:

  • Para una lógica ligera que se pueda ejecutar rápidamente, en línea
  • El proxy de la API debe transferir contexto (como variables) o recibir contexto de la implementación externa.

En resumen:

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

En la siguiente imagen se ilustra este proceso: