Mejores prácticas para el diseño y desarrollo de proxy API con Apigee

Esta página se aplica a Apigee y Apigee híbrido .

Ver la documentación de Apigee Edge .

Este documento proporciona un conjunto de mejores prácticas para desarrollar servidores proxy API con Apigee.

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

Además de las pautas que se encuentran aquí, también puede resultarle útil Introducción a los antipatrones .

Estándares de desarrollo

Comentarios y documentación

  • Proporcione comentarios en línea en las configuraciones de ProxyEndpoint y TargetEndpoint . Los comentarios mejoran la legibilidad de un flujo, especialmente cuando los nombres de los archivos de política no son lo suficientemente descriptivos para expresar la funcionalidad subyacente del flujo.
  • Haz que tus comentarios sean útiles. Evita comentarios obvios.
  • Utilice sangría, espaciado, alineación vertical, etc. consistentes.

Codificación de estilo framework

La programación al estilo framework implica almacenar recursos de proxy de API en su propio sistema de control de versiones para su reutilización en entornos de desarrollo locales. Por ejemplo, para reutilizar una política, almacénela en el control de código fuente para que los desarrolladores puedan sincronizarla y usarla en sus propios entornos de desarrollo proxy.

  • Para habilitar DRY (no se repita), siempre que sea posible, las configuraciones de políticas y los scripts deben implementar funciones especializadas y reutilizables. Por ejemplo, una política dedicada a extraer parámetros de consulta de los mensajes de solicitud podría llamarse ExtractVariables.ExtractRequestParameters .
  • Limpie las políticas y los recursos no utilizados (JavaScript, Java, XSLT, ) de los servidores proxy de API, especialmente los recursos grandes que tienen el potencial de ralentizar los procedimientos de importación e implementación.

Convenciones de nomenclatura

  • El atributo name política y el nombre del archivo de política XML deben ser idénticos.
  • El atributo name política de la política 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 para alguien que nunca haya trabajado antes con ese proxy API.
  • Asigne nombres a las políticas según su función. Apigee recomienda establecer una convención de nomenclatura coherente para sus políticas. Por ejemplo, utilice prefijos cortos seguidos de una secuencia de palabras descriptivas separadas por guiones. Por ejemplo, AM-xxx para la política AssignMessage . Consulte también la herramienta apigeelint .
  • Utilice 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 elige un estilo, como camelCase o under_score, úselo en todo el proxy de la API.
  • Utilice prefijos de variables, siempre que sea posible, para organizar las variables según su propósito, por ejemplo, Consumer.username y Consumer.password .

Desarrollo de proxy API

Consideraciones iniciales de diseño

  • Para obtener orientación sobre el diseño de API RESTful, descargue el libro electrónico Diseño de API web: el eslabón perdido .
  • Aproveche las políticas y funcionalidades de Apigee siempre que sea posible para crear proxies de API. Evite codificar toda la lógica del proxy en recursos de JavaScript, Java o Python.
  • Construya flujos de forma organizada. Es preferible tener varios flujos, cada uno con una sola condición, a múltiples conexiones condicionales al mismo preflujo y posflujo.
  • Como medida de seguridad, cree un proxy de API predeterminado con una ruta base ProxyEndpoint de / . Esto puede usarse para redirigir las solicitudes de API base a un sitio de desarrollador, devolver una respuesta personalizada o realizar otra acción más útil que devolver el valor predeterminado de messaging.adaptors.http.flow.ApplicationNotFound .
  • Para un rendimiento óptimo, Apigee recomienda no usar más de 3000 rutas base de proxy de API por entorno o grupo de entornos. Superar esta recomendación puede resultar en una mayor latencia para todas las implementaciones de proxy de API, tanto nuevas como existentes.
  • Utilice los recursos de TargetServer para desacoplar las configuraciones de TargetEndpoint de las URL concretas, lo que favorece la promoción en todos los entornos.
    Consulte Equilibrio de carga entre servidores back-end .
  • Si tiene varias RouteRules, cree una como predeterminada, es decir, una RouteRule sin condición. Asegúrese de que la RouteRule predeterminada sea la última en la lista de rutas condicionales. Las RouteRules se evalúan de arriba a abajo en ProxyEndpoint. Consulte la referencia de configuración del proxy de la API .
  • Tamaño del paquete de proxy de API: los paquetes de proxy de API no pueden tener más de 15 MB.
  • Control de versiones de API: para conocer las ideas y recomendaciones de Apigee sobre el control de versiones de API, consulte Control de versiones en el libro electrónico Diseño de API web: el eslabón perdido .

Habilitación de CORS

Antes de publicar sus API, deberá agregar la política CORS al PreFlow de solicitud de ProxyEndpoint para admitir solicitudes de origen cruzado del lado del cliente.

CORS (Intercambio de recursos entre orígenes) 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 común para la política del mismo origen , implementada por todos los navegadores. Por ejemplo, si realiza una llamada XHR a la API de Twitter desde código JavaScript que se ejecuta en su navegador, la llamada fallará. Esto se debe a que el dominio que sirve la página a su navegador no es el mismo que sirve la API de Twitter. CORS ofrece una solución a este problema al permitir que los servidores la acepten si desean proporcionar intercambio de recursos entre orígenes.

Para obtener información sobre cómo habilitar CORS en sus servidores proxy de API antes de publicar las API, consulte Cómo agregar compatibilidad con CORS a un servidor proxy de API .

Tamaño de la carga útil del mensaje

El tamaño de la carga útil de los mensajes en los flujos de solicitud o respuesta de Apigee está limitado a 10 MB por defecto . Los usuarios que requieran procesar una carga útil grande pueden configurar un límite mayor mediante el elemento <Properties> en las configuraciones ProxyEndpoint o TargetEndpoint de sus proxies de API.

Para obtener más información sobre el uso de las propiedades response.payload.parse.limit o request.payload.parse.limit para configurar un tamaño de carga útil máximo de hasta 30 MB para flujos de solicitud o respuesta, consulte la referencia de configuración de proxy de API .

Tenga en cuenta que exceder el tamaño de mensaje especificado genera un error protocol.http.TooBigBody .

Tenga en cuenta las siguientes estrategias recomendadas para manejar mensajes de gran tamaño en Apigee:

  • Recomendamos encarecidamente aislar los proxies de API que gestionan con frecuencia cargas útiles grandes en un entorno dedicado para evitar un posible escenario de "vecino ruidoso". Los proxies que gestionan cargas útiles grandes consumen más recursos de CPU y memoria del sistema, especialmente cuando se utilizan junto con políticas que interactúan con ellas.
  • También recomendamos limitar el uso de políticas para interactuar con cargas útiles de gran tamaño. Usar políticas para analizar y copiar repetidamente las cargas útiles de solicitud o respuesta puede afectar negativamente el rendimiento del sistema.
  • Se recomienda a las organizaciones que manejan grandes volúmenes de solicitudes de alta carga que proporcionen direcciones IP adicionales para evitar el agotamiento de los puertos debido al escalamiento horizontal.
  • Considere la posibilidad de transmitir solicitudes y respuestas. Tenga en cuenta que, al transmitir, las políticas ya no tienen acceso al contenido del mensaje. Consulte "Transmitir solicitudes y respuestas" .
  • Si su organización utiliza facturación de pago por uso , recomendamos utilizar límites configurables para cargas útiles grandes solo para servidores proxy API implementados en un entorno integral.

Manejo de fallas

  • Utilice FaultRules para gestionar todos los fallos. (Las políticas RaiseFault se utilizan para detener el flujo de mensajes y enviar el procesamiento al flujo FaultRules).
  • Dentro del flujo de reglas de fallo, utilice una política AssignMessage para generar la respuesta al fallo, no una política RaiseFault . Ejecute las políticas AssignMessage condicionalmente según el tipo de fallo que se produzca.
  • Siempre incluye un controlador de fallas "general" 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, siempre haga que las respuestas a fallas coincidan con los formatos estándar disponibles en su empresa o proyecto.
  • Utilice mensajes de error significativos y legibles para humanos que sugieran una solución a la condición de error.

Consulte Manejo de fallos .

Persistencia

Mapas de clave/valor

  • Utilice mapas 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 utilizar mapas clave/valor, ya que esta información se almacena en la base de datos de Cassandra.

Consulte 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 GET. Las creaciones, actualizaciones y eliminaciones no deben almacenarse en caché. <SkipCachePopulation>response.status.code != 200 or request.verb != "GET"</SkipCachePopulation>
  • Rellene la caché con un único tipo de contenido consistente (por ejemplo, XML o JSON). Tras recuperar una entrada de responseCache, conviértala al tipo de contenido necesario con JSONtoXML o XMLToJSON. Esto evitará almacenar datos duplicados, triples o incluso más.
  • Asegúrese de que la clave de caché sea suficiente para los requisitos de almacenamiento en caché. En muchos casos, request.querystring puede usarse como identificador único.
  • No incluya la clave API ( client_id ) en la clave de caché, a menos que se requiera explícitamente. Normalmente, las API protegidas únicamente por una clave devolverán los mismos datos a todos los clientes para una solicitud determinada. Es ineficiente almacenar el mismo valor para varias entradas basándose en la clave API.
  • Establezca intervalos de expiración de caché adecuados para evitar lecturas sucias.
  • Siempre que sea posible, intente que la política de caché de respuesta que la llena se ejecute en el PostFlow de respuesta de ProxyEndpoint lo más tarde posible. En otras palabras, que se ejecute después de los pasos de traducción y mediación, incluyendo la mediación basada en JavaScript y la conversión entre JSON y XML. Al almacenar en caché los datos mediados, se evita el coste de rendimiento que supone ejecutar el paso de mediación cada vez que se recuperan datos almacenados en caché.

    Tenga en cuenta que es posible que desee almacenar en caché datos no mediados si la mediación genera una respuesta diferente de una solicitud a otra.

  • La política de caché de respuesta para buscar la entrada de caché debe aparecer en el preflujo de la solicitud ProxyEndpoint. Evite implementar demasiada lógica, aparte de la generación de claves de caché, antes de devolver una entrada de caché. De lo contrario, se minimizan las ventajas del almacenamiento en caché.
  • En general, siempre debe mantener la búsqueda de la caché de respuestas lo más cerca posible de la solicitud del cliente. Por otro lado, debe mantener la carga de la caché de respuestas lo más cerca posible de la respuesta del cliente.
  • Al utilizar múltiples políticas de caché de respuesta diferentes en un proxy, siga estas pautas para garantizar un comportamiento discreto para cada una:
    • Ejecute cada política según condiciones mutuamente excluyentes. Esto ayudará a garantizar que solo se ejecute una de las múltiples políticas de caché de respuesta.
    • Defina diferentes recursos de caché para cada política de caché de respuesta. El recurso de caché se especifica en el elemento <CacheResource> de la política.

Consulte la política de ResponseCache .

Política y código personalizado

¿Política o código personalizado?

  • Utilice las políticas integradas ante todo (siempre que sea posible). Las políticas de Apigee están reforzadas, optimizadas y soportadas. Por ejemplo, utilice las políticas estándar AssignMessage y ExtractVariables en lugar de JavaScript (siempre que sea posible) para crear cargas útiles, extraer información de ellas (XPath, JSONPath), etc.
  • Se prefiere JavaScript a Python y Java. Sin embargo, si el rendimiento es el requisito principal, se recomienda usar Java en lugar de JavaScript.

JavaScript

  • Utilice JavaScript si es más intuitivo que las políticas de Apigee (por ejemplo, al configurar target.url para muchas combinaciones de URI diferentes).
  • Análisis de carga útil compleja, como iteración a través de un objeto JSON y codificación/decodificación Base64.
  • La política de JavaScript tiene un límite de tiempo, por lo que los bucles infinitos están bloqueados.
  • Utilice siempre los pasos de JavaScript y guarde los archivos en la carpeta de recursos jsc . La política de JavaScript precompila el código durante la implementación.

Java

  • Utilice Java si el rendimiento es la máxima prioridad o si la lógica no se puede implementar en JavaScript.
  • Incluir archivos fuente de Java en el seguimiento del código fuente.

Consulte la política JavaCallout para obtener información sobre el uso de Java en servidores proxy de API.

Pitón

  • No use Python a menos que sea absolutamente necesario. Los scripts de Python pueden generar cuellos de botella en el rendimiento en ejecuciones simples, ya que se interpretan en tiempo de ejecución.

Llamadas de script (Java, JavaScript, Python)

  • Utilice un try/catch global o equivalente.
  • Lanza excepciones significativas y captúralas adecuadamente para usarlas en respuestas de fallas.
  • Lanza y captura excepciones con anticipación. No uses el método try/catch global para gestionar todas las excepciones.
  • Realice comprobaciones de valores nulos e indefinidos cuando sea necesario. Un ejemplo de cuándo hacerlo es al recuperar variables de flujo opcionales.
  • Evite realizar 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 API admite XML a través de E4X .

Véase modelo de objetos de JavaScript .

Java

  • Al acceder a las cargas útiles de los mensajes, intente usar context.getMessage() en lugar de context.getResponseMessage o context.getRequestMessage . Esto garantiza que el código pueda recuperar la carga útil, tanto en el flujo de solicitud como en el de respuesta.
  • Importe bibliotecas a la organización o entorno de Apigee y no las incluya en el archivo JAR. Esto reduce el tamaño del paquete y permite que otros archivos JAR accedan al mismo repositorio de bibliotecas.
  • Importe archivos JAR mediante 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 proxys de API hagan referencia a los mismos archivos JAR. Otra ventaja es el aislamiento del cargador de clases.
  • No utilice Java para el manejo de recursos (por ejemplo, crear y administrar grupos de subprocesos).

Pitón

  • Lanzar excepciones significativas y capturarlas adecuadamente para usarlas en respuestas de fallas de Apigee

Consulte la política de PythonScript .

Llamadas de servicio

  • Existen muchos casos de uso válidos para el encadenamiento de proxy, donde se utiliza una llamada de servicio en un proxy de API para llamar a otro. Si se utiliza el encadenamiento de proxy, asegúrese de evitar llamadas recursivas en bucles infinitos al mismo proxy de API.

    Si se conecta entre servidores proxy que están en la misma organización y entorno, asegúrese de consultar Encadenamiento de servidores proxy de API para obtener más información sobre cómo implementar una conexión local que evite una sobrecarga de red innecesaria.

  • Cree un mensaje de solicitud ServiceCallout con la política AssignMessage y rellene 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 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 .
  • Almacene el objeto de respuesta de un ServiceCallout en una variable de mensaje independiente. Posteriormente, puede analizar la variable de mensaje y conservar la carga útil original del mensaje para que la utilicen otras políticas.

Consulte la política de ServiceCallout .

Acceder a entidades

Política de AccessEntity

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

Consulte la política de AccessEntity .

Explotación florestal

  • Utilice una política de syslog común para todos los paquetes y dentro del mismo paquete. Esto mantendrá un formato de registro consistente.

Consulte la política de registro de mensajes .

Escucha

Los clientes de la nube no están obligados a revisar componentes individuales de Apigee (enrutadores, procesadores de mensajes, etc.). El equipo de Operaciones Globales de Apigee supervisa exhaustivamente todos los componentes, junto con las comprobaciones del estado de la API, a petición del cliente.

Análisis de Apigee

El análisis puede proporcionar una supervisión de API no crítica a medida que se miden los porcentajes de error.

Ver paneles de análisis .

Depurar

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

Consulte Uso de la herramienta de depuración .

Seguridad

Lógica personalizada en servidores proxy API

Un requisito común al crear proxies de API es incluir lógica para procesar solicitudes o respuestas. Si bien muchos requisitos se pueden cumplir con un conjunto predefinido de pasos, acciones y políticas, como verificar un token, aplicar una cuota o responder con un objeto en caché, a menudo se requiere acceso a la programabilidad. Por ejemplo, buscar una ubicación (punto final) en una tabla de enrutamiento basándose en una clave encontrada en una solicitud y aplicar dinámicamente un punto final de destino o un método de autenticación personalizado o propietario, etc.

Apigee ofrece a los desarrolladores múltiples opciones para gestionar dicha lógica personalizada. Este documento explorará dichas opciones y cuándo usarlas:

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

Cuándo utilizarlo:

  • Las políticas de JavaScript y PythonScript tienen capacidades equivalentes. La familiaridad de un desarrollador con un lenguaje suele ser la motivación para elegir uno sobre el otro.
  • Las políticas de JavaScript y PythonScript son las más adecuadas para procesar lógica en línea que no sea demasiado compleja y no requiera el uso de bibliotecas de terceros.
  • Estas políticas no son tan eficientes como la política JavaCallout.

Cuándo no utilizar:

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

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

Llamada de Java

Cuándo utilizarlo:

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

Cuándo no utilizar:

  • La API Gateway de Apigee no es un servidor de aplicaciones ni está diseñada para cargar frameworks como Spring, JEE, etc. Si la llamada suele tardar más de un segundo en procesarse, la lógica puede considerarse funcional (lógica de negocio). Considere externalizarla como un servicio.
  • Para proteger la puerta de enlace de la API de Apigee contra abusos, se aplican restricciones al tipo de código ejecutable. Por ejemplo, se bloquea la ejecución del código Java que intenta acceder a ciertas bibliotecas criptográficas o al sistema de archivos.
  • Las aplicaciones Java, especialmente las que dependen de bibliotecas de terceros, pueden incorporar numerosos archivos JAR (de gran tamaño). Esto puede ralentizar el arranque de las puertas de enlace.
Llamada externa

Cuándo utilizarlo:

  • Ideal para externalizar la lógica personalizada y permitir que la lógica personalizada acceda (y si es necesario modifique) el contexto del mensaje.
  • Las llamadas externas implementan gRPC y pueden tener un mejor rendimiento que un ServiceCallout.
  • Al utilizar Apigee o Apigee híbrido en Google Cloud, considere usar Cloud Functions o Cloud Run para alojar dicha lógica.
  • Como reemplazo efectivo de la función de objetivos alojados en Apigee Edge.

Cuando no se utiliza:

  • Para una lógica liviana que pueda ejecutarse rápidamente, en línea.
Llamada de servicio

Cuándo utilizarlo:

  • 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 punto final REST/SOAP/GraphQL ya existe o se puede implementar fácilmente
  • Al utilizar Apigee o Apigee híbrido en Google Cloud, considere usar Cloud Functions o Cloud Run para alojar dicha lógica.
  • Como reemplazo efectivo de la función de objetivos alojados en Apigee Edge.

Cuando no se utiliza:

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

Para resumir:

  1. Si la lógica es simple o trivial, utilice JavaScript (preferiblemente) o PythonScript.
  2. Si la lógica en línea requiere un mejor rendimiento que JavaScript o PythonScript, utilice JavaCallout.
  3. Si la lógica debe externalizarse, utilice ExternalCallout.
  4. Si ya tiene implementaciones externas y/o los desarrolladores están familiarizados con REST, utilice ServiceCallout.

La siguiente figura ilustra este proceso: