Recomendaciones para el rendimiento de microservicios

El desarrollo de software consiste en realizar concesiones, y los microservicios no son una excepción. Lo que ganas en la implementación de código y en la independencia de operación, lo pagas en sobrecarga de rendimiento. Esta sección proporciona algunas recomendaciones sobre los pasos que puedes seguir para minimizar este impacto.

Convertir operaciones CRUD en microservicios

Los microservicios son especialmente apropiados para las entidades a las que se accede con el patrón crear, recuperar, actualizar y borrar (CRUD). Cuando trabajas con tales entidades, normalmente usas solo una entidad a la vez, como un usuario, y normalmente realizas solo una de las acciones de CRUD a la vez. Por lo tanto, solo necesitas una llamada de microservicio para la operación. Busca entidades que tengan operaciones CRUD más un conjunto de métodos comerciales que podrían utilizarse en muchas partes de tu aplicación. Estas entidades son buenas candidatas para los microservicios.

Proporcionar API en lotes

Además de las API de estilo CRUD, aún puedes proporcionar un buen rendimiento de microservicio para grupos de entidades mediante API en lotes. Por ejemplo, en lugar de solo exponer un método de la API GET que recupera un solo usuario, proporciona una API que tome un conjunto de ID de usuario y muestre un diccionario de usuarios correspondientes:

Solicitud:

/user-service/v1/?userId=ABC123&userId=DEF456&userId=GHI789

Respuesta:

{
  "ABC123": {
    "userId": "ABC123",
    "firstName": "Jake",
    … },
  "DEF456": {
    "userId": "DEF456",
    "firstName": "Sue",
    … },
  "GHI789": {
    "userId": "GHI789",
    "firstName": "Ted",
    … }
}

El SDK de App Engine admite muchas API en lotes, como la capacidad de recuperar muchas entidades de Cloud Datastore a través de un solo RPC, por lo que el servicio de estos tipos de API en lotes puede ser muy eficiente.

Usar solicitudes asíncronas

A menudo, necesitarás interactuar con varios microservicios para redactar una respuesta. Por ejemplo, es posible que necesites recuperar las preferencias de acceso del usuario, así como los detalles de su empresa. Habitualmente, estos datos no dependen uno del otro y puedes recuperarlos en paralelo. La biblioteca Urlfetch del SDK de App Engine admite solicitudes asíncronas, lo que te permite llamar a microservicios en paralelo.

Usar la ruta más corta

Según cómo invoques Urlfetch, puedes dar lugar a que se usen diferentes infraestructuras y rutas. Para usar la ruta con mejor rendimiento, considera las recomendaciones siguientes:

Usa *.appspot.com, no un dominio personalizado
Un dominio personalizado da lugar a que se use una ruta diferente cuando se enruta a través de la infraestructura de Google. Como tus llamadas de microservicios son internas, es más fácil y funciona mejor si usas tu nombre de host my-app.appspot.com.
Configura follow_redirects como False
Configura explícitamente follow_redirects=False cuando llames a Urlfetch, ya que evita un servicio más pesado diseñado para seguir redireccionamientos. Tus extremos de API no deberían necesitar redireccionar los clientes porque son tus propios microservicios, y los extremos solo deben mostrar respuesta de serie HTTP 200, 400 y 500.
Utiliza servicios dentro de un proyecto mejor que sobre varios proyectos
Hay buenas razones para usar varios proyectos cuando compilas una aplicación basada en microservicios, pero si tu objetivo principal es el rendimiento, usa servicios dentro de un solo proyecto. Los servicios de un proyecto se alojan en un mismo centro de datos y aunque la capacidad de procesamiento en la red de centro de datos interno de Google es excelente, las llamadas locales son más rápidas.

Evitar las conversaciones durante la aplicación de la seguridad

Es malo para el rendimiento utilizar mecanismos de seguridad que implican muchas comunicaciones para autenticar la API de llamada. Por ejemplo, si tu microservicio necesita validar un ticket de tu aplicación llamando a la aplicación, generarás una serie de idas y vueltas para obtener tus datos.

Una implementación de OAuth2 puede amortizar este costo a lo largo del tiempo usando tokens de actualización y almacenando en caché un token de acceso entre las invocaciones Urlfetch. Sin embargo, si el token de acceso almacenado en caché se guarda en Memcache, necesitarás generar una sobrecarga de Memcache para recuperarlo. Para evitar esta sobrecarga, puedes almacenar en caché el token de acceso en una memoria de instancia, pero seguirás experimentando la actividad OAuth2 con frecuencia, ya que cada nueva instancia negocia un token de acceso; recuerda que las instancias de App Engine se activan y desactivan con frecuencia. Algunos híbridos de Memcache y la caché de instancia te ayudarán a mitigar este problema, pero aumentará la complejidad de tu solución.

Otro enfoque que funciona bien es compartir un token secreto entre los microservicios, por ejemplo, transmitido como un encabezado HTTP personalizado. En este enfoque, cada microservicio podría tener un token único para cada emisor. Por lo general, los secretos compartidos son una opción cuestionable para las implementaciones de seguridad, pero, como todos los microservicios están en la misma aplicación, se convierte en un problema menor dadas las ganancias de rendimiento. Con un secreto compartido, el microservicio solo necesita realizar una comparación de strings del secreto entrante con un diccionario probablemente en memoria, y la aplicación de la seguridad es muy ligera.

Si todos los microservicios están en App Engine, también puedes inspeccionar el encabezado X-Appengine-Inbound-Appid entrante. Este encabezado es agregado por la infraestructura de Urlfetch cuando se realiza una solicitud a otro proyecto de App Engine y no se puede establecer por un tercero. Según los requisitos de seguridad, tus microservicios podrían inspeccionar este encabezado entrante para aplicar tu política de seguridad.

Realizar el seguimiento de solicitudes de microservicio

A medida que compilas tu aplicación basada en microservicios, comienzas a acumular una sobrecarga de llamadas sucesivas de Urlfetch. Cuando esto sucede, puedes usar Cloud Trace para comprender qué llamadas se están realizando y dónde se encuentra la sobrecarga. Es importante destacar que Cloud Trace también puede ayudar a identificar dónde se están invocando microservicios independientes en serie, para que puedas refactorizar tu código y realizar estas recuperaciones en paralelo.

Se activa una característica útil de Cloud Trace cuando usas varios servicios dentro de un solo proyecto. A medida que se realizan llamadas entre los servicios de microservicio en tu proyecto, Cloud Trace contrae todas las llamadas en un solo grafo de llamadas para permitirte visualizar la solicitud completa de extremo a extremo como un solo registro.

Captura de pantalla de Google Cloud Trace

Ten en cuenta que en el ejemplo anterior, las llamadas a pref-service y user-service se realizan en paralelo mediante el uso de un Urlfetch asíncrono, por lo que las RPC aparecen mezcladas en la visualización. Sin embargo, esta sigue siendo una herramienta valiosa para diagnosticar la latencia.

Pasos siguientes

¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Entorno estándar de App Engine para Java 8