Parte 1: Cómo construir una API gateway para microservicios usando OpenResty
API7.ai
January 20, 2023
En este artículo, pasemos a los capítulos sobre OpenResty en acción. Utilizaré tres capítulos para presentarte cómo implementar una puerta de enlace de API para microservicios. En este proceso, no solo involucraremos los conocimientos de OpenResty que hemos aprendido anteriormente, sino que también te mostraré cómo construir un nuevo producto y proyecto de código abierto desde cero, desde múltiples dimensiones como la industria, el producto y la selección de tecnología.
¿Qué hace una puerta de enlace de API para microservicios?
Primero, veamos el papel de la puerta de enlace de API para microservicios. La siguiente imagen es una breve descripción:
Como todos sabemos, la puerta de enlace de API no es un concepto nuevo. Existe desde hace más de diez años. Su función principal es servir como la entrada del tráfico y procesar las solicitudes relacionadas con el negocio de manera unificada. De esta manera, las solicitudes pueden procesarse de manera más segura, rápida y precisa. Tiene las siguientes funciones tradicionales:
- Proxy inverso y balanceo de carga, que son consistentes con el posicionamiento y las funciones de NGINX;
- Funciones dinámicas como upstream dinámico, certificado SSL dinámico y limitación de corriente y tasa en tiempo de ejecución, son funciones que la versión de código abierto de NGINX no tiene;
- Verificaciones de salud activas y pasivas de los upstreams, así como cortocircuitos de servicio;
- Expandirse basándose en la puerta de enlace de API para convertirse en una plataforma de gestión de API de ciclo completo.
En los últimos años, el tráfico relacionado con el negocio ya no es iniciado solo por clientes de PC y navegadores, sino más por teléfonos móviles y dispositivos IoT. Con la popularización del 5G en el futuro, este tráfico aumentará. Al mismo tiempo, a medida que cambia la estructura de la arquitectura de microservicios, el tráfico entre servicios también comienza a crecer explosivamente. En este nuevo escenario de negocio, naturalmente han surgido más funciones avanzadas de la puerta de enlace de API:
- Compatible con cloud-native, la arquitectura debe ser ligera y fácil de contenerizar.
- Conexión con componentes de estadísticas y monitoreo como
Prometheus
,Zipkin
,SkyWalking
. - Soporte para proxy
gRPC
, y conversión de protocolo entreHTTP
ygRPC
, convirtiendo la solicitudHTTP
del usuario en una solicitudgRPC
del servicio interno. - Asumir el rol de OpenID Relying Party, conectarse con servicios de proveedores de autenticación como Auth0 y Okta, y tratar la seguridad del tráfico como una prioridad máxima.
- Implementar Serverless ejecutando funciones de usuario dinámicamente en tiempo de ejecución, haciendo que los nodos de borde de la puerta de enlace sean más flexibles.
- No encerrar a los usuarios y soportar arquitecturas de despliegue en nube híbrida.
- El nodo de la puerta de enlace debe ser sin estado y poder expandirse y reducirse a voluntad.
Cuando una puerta de enlace de API para microservicios tiene las funciones mencionadas anteriormente, el servicio del usuario solo necesita preocuparse por el negocio en sí. Aquellas funciones que no tienen nada que ver con la implementación del negocio pueden resolverse en el nivel independiente de la puerta de enlace. Por ejemplo, descubrimiento de servicios, cortocircuitos, autenticación, limitación de tasa, estadísticas, análisis de rendimiento, etc.
Desde este punto de vista, la puerta de enlace de API puede reemplazar todas las funciones de NGINX y manejar el tráfico norte-sur; también puede completar el rol del plano de control de Istio
y el plano de datos de Envoy
para manejar el tráfico este-oeste.
¿Por qué reinventar la rueda?
Debido a que el estado de la puerta de enlace de API para microservicios es tan importante, siempre ha sido un campo de batalla, y los gigantes tradicionales de TI han estado en este campo durante mucho tiempo. Según el Informe del Ciclo de Vida de API publicado por Gartner en 2018, Google, CA, IBM, Red Hat y Salesforce son los principales fabricantes, y Apache APISIX, más familiar para los desarrolladores, está entre los visionarios.
Entonces, la pregunta es, ¿por qué tenemos que reinventar una nueva rueda?
En pocas palabras, esto se debe a que ninguna de las puertas de enlace de API actuales para microservicios es adecuada para nuestras necesidades. Primero, veamos los productos comerciales de código cerrado. Tienen funciones completas, cubren todo el ciclo de vida de la gestión de API, diseño de API, SDK multilingüe, documentación, pruebas y lanzamiento, y ofrecen servicios SaaS. Algunos están integrados con la nube pública, lo cual es muy conveniente de usar. Pero al mismo tiempo, también traen dos puntos dolorosos.
El primer punto doloroso es el problema del encierro en la plataforma. La puerta de enlace de API es la entrada del tráfico de negocio. A diferencia del tráfico no relacionado con el negocio acelerado por CDN como imágenes y videos, que pueden migrarse a voluntad, la puerta de enlace de API vinculará mucha lógica relacionada con el negocio. Una vez que uses una solución de código cerrado, es difícil migrar a otras plataformas de manera fluida y a bajo costo.
El segundo punto doloroso es el problema de que no se puede desarrollar nuevamente. Generalmente, las empresas grandes y medianas tendrán sus propias necesidades únicas y necesitarán desarrollo personalizado, pero en este momento solo puedes depender del fabricante y no puedes hacer desarrollo secundario.
Esta es una de las razones por las que las soluciones de puerta de enlace de API de código abierto se han vuelto populares. Sin embargo, los productos de código abierto existentes no son omnipotentes y también tienen muchas deficiencias:
- Dependen de bases de datos relacionales como PostgreSQL y MySQL. De esta manera, el nodo de la puerta de enlace solo puede sondear la base de datos cuando cambia la configuración. Esto no solo hace que la configuración tarde en surtir efecto, sino que también agrega complejidad al código, dificultando su comprensión. Al mismo tiempo, la base de datos también se convertirá en un punto único y un cuello de botella de rendimiento del sistema, lo que no garantiza una alta disponibilidad general. Si usas la puerta de enlace de API en un entorno Kubernetes, la base de datos relacional será más engorrosa, lo que no es propicio para un escalado rápido.
- Los complementos no se pueden cargar en caliente. Cuando agregas un nuevo complemento o modificas el código de un complemento existente, debes recargar el servicio para que surta efecto. Esto es lo mismo que la necesidad de recargar después de modificar la configuración de NGINX, lo que afectará las solicitudes de los usuarios.
- La estructura del código es compleja y difícil de entender. Algunos proyectos de código abierto han hecho encapsulaciones orientadas a objetos de múltiples capas, y algunas lógicas simples se han vuelto confusas. Pero, para el escenario de la puerta de enlace de API, la expresión directa será más clara y eficiente, y también es más propicia para el desarrollo secundario.
Por lo tanto, necesitamos una puerta de enlace de API más ligera, compatible con cloud-native y amigable para el desarrollo. Por supuesto, no podemos construir un automóvil a puerta cerrada. Necesitamos comprender profundamente las características de las puertas de enlace de API existentes. En este momento, el panorama de la Cloud Native Software Foundation (CNCF) es una buena referencia:
Componentes y conceptos principales de la puerta de enlace de API
Por supuesto, antes de implementarla, necesitamos comprender los componentes principales de la puerta de enlace de API. Según las funciones de la puerta de enlace de API que mencionamos anteriormente, necesita al menos los siguientes componentes para comenzar a funcionar.
El primero es Route
. Coincide con la solicitud del cliente definiendo algunas reglas, luego carga y ejecuta el complemento correspondiente según el resultado de la coincidencia, y reenvía la solicitud al upstream especificado. Estas reglas de coincidencia de ruta pueden estar compuestas por host
, uri
, header
, etc. La ubicación familiar en NGINX es una implementación de enrutamiento.
El segundo es el complemento, el alma de la puerta de enlace de API. Funciones como autenticación, limitación de tráfico y tasa, restricción de IP, Prometheus, Zipkin, etc., se implementan a través de complementos. Dado que es un complemento, debe ser plug-and-play; además, los complementos no pueden interactuar entre sí. Al igual que construimos bloques de Lego, necesitamos usar reglas uniformes e interfaces de desarrollo acordadas para interactuar con la capa inferior.
A continuación está el schema
. Dado que es una puerta de enlace para procesar API, es necesario verificar el formato de la API, como tipos de datos, contenido de campo permitido, campos que deben cargarse, etc. En este momento, se necesita una capa de schema
para una definición e inspección unificada e independiente.
Por último está el almacenamiento. Se utiliza para almacenar varias configuraciones de los usuarios y es responsable de enviarlas a todos los nodos de la puerta de enlace cuando hay un cambio. Este es un componente básico muy crítico en la capa inferior. Su selección determina cómo se escriben los complementos de la capa superior, si el sistema puede mantener una alta disponibilidad y escalabilidad, etc., por lo que debemos tomar una decisión cuidadosa.
Además, sobre estos componentes principales, también necesitamos abstraer varios conceptos comunes de las puertas de enlace de API, que son comunes entre diferentes puertas de enlace de API.
Ruta
Hablemos primero de Route
. Una ruta contendrá tres partes: condiciones de coincidencia, complementos vinculados y upstream, como se muestra en la siguiente figura:
Podemos completar todas las configuraciones directamente en Route
, lo cual es lo más fácil. Pero en el caso de muchas API y upstreams, hacerlo causará muchas configuraciones duplicadas. En este momento, necesitamos los dos conceptos de Service
y Upstream
para hacer una capa de abstracción.
Servicio
Veamos Service
a continuación. Es una abstracción de un cierto tipo de API, y también puede entenderse como una abstracción de un grupo de Route
s. Por lo general, tiene una correspondencia 1:1
con los servicios upstream, y la relación entre Route
s y Service
s suele ser N:1
. También usé una imagen para representarlo:
A través de esta capa de abstracción de Service
, podemos separar los Plugin
s y Upstream
s duplicados. De esta manera, cuando el Plugin
y el Upstream
cambian, solo necesitamos modificar el Service
en lugar de modificar los datos vinculados en múltiples Route
s.
Upstream
Finalmente, hablemos de Upstream
. Continuando con el ejemplo anterior, si los upstreams en los dos Route
s son los mismos, pero los complementos vinculados son diferentes, entonces podemos abstraer los upstreams por separado, como se muestra en la siguiente figura:
De esta manera, cuando el nodo upstream cambia, Route
no tiene idea, y todo se procesa dentro de Upstream
.
Del proceso de derivación de estos tres conceptos principales, también podemos ver que estas abstracciones se basan en escenarios de uso práctico en lugar de imaginación. Se aplican a todas las puertas de enlace de API, independientemente de las soluciones técnicas específicas.
Resumen
En este artículo, presentamos el papel, las funciones, los componentes principales y los conceptos abstractos de la puerta de enlace de API para microservicios, que son la base de la puerta de enlace de API.
Aquí hay una pregunta para que pienses: "Con respecto al tráfico tradicional norte-sur y el tráfico este-oeste entre microservicios, ¿crees que la puerta de enlace de API puede manejar ambos?" Si ya estás usando una puerta de enlace de API, también puedes escribir tus pensamientos sobre la selección de tecnología. Bienvenido a comunicarte y discutir, y te invitamos a compartir este artículo con tus colegas y amigos para aprender y progresar juntos.
Próximamente: Parte 2: Cómo construir una puerta de enlace de API para microservicios usando OpenResty Parte 3: Cómo construir una puerta de enlace de API para microservicios usando OpenResty