Sesiones Persistentes con Apache APISIX - Teoría
July 27, 2023
Las sesiones persistentes, también conocidas como afinidad de sesión, son un mecanismo mediante el cual un componente de enrutamiento que actúa como fachada siempre dirige una solicitud al mismo nodo subyacente. En esta publicación, describiré la razón detrás de las sesiones persistentes, las alternativas disponibles y cómo implementarlas mediante Apache APISIX.
¿Por qué sesiones persistentes?
Las sesiones persistentes se popularizaron cuando almacenábamos el estado en el nodo subyacente, no en la base de datos. Usaré el ejemplo de una tienda de comercio electrónico simplificada para explicarlo mejor.
Los fundamentos básicos de un sitio pequeño de comercio electrónico pueden consistir en una aplicación web y una base de datos.
Si el negocio tiene éxito, crecerá y en algún momento necesitarás escalar esta arquitectura. Una vez que no puedas escalar verticalmente (máquinas más grandes), deberás escalar horizontalmente (más nodos). Con nodos adicionales de la aplicación, también necesitarás un mecanismo de balanceo de carga frente a los nodos de la aplicación web para distribuir la carga entre ellos.
Ir a la base de datos cada vez es una operación costosa. Está bien para datos a los que se accede con poca frecuencia. Sin embargo, queremos mostrar el contenido del carrito en cada solicitud. Hay un par de alternativas disponibles para acelerar las cosas. Si asumimos que la aplicación web usa renderización del lado del servidor, la solución clásica es mantener los datos relacionados con el carrito en la memoria del nodo de la aplicación web.
Sin embargo, si almacenamos el carrito del usuario X en el nodo 1, debemos asegurarnos de que cada solicitud del usuario X se dirija al mismo nodo. De lo contrario, sentirán que perdieron el contenido de su carrito. Las sesiones persistentes, o afinidad de sesión, es el mecanismo que dirige consistentemente al mismo usuario al mismo nodo.
Limitación de las sesiones persistentes
Antes de continuar, debo explicar una limitación importante de las sesiones persistentes. Si el nodo de la aplicación web que almacena los datos se cae por cualquier motivo, los datos se pierden irremediablemente. Para el escenario de comercio electrónico anterior, esto significa que los usuarios perderán su carrito ocasionalmente, lo cual es inaceptable desde un punto de vista comercial.
Por esta razón, las sesiones persistentes deben ir de la mano con la replicación de sesiones: los datos almacenados en un nodo deben copiarse y mantenerse sincronizados con todos los demás nodos.
Aunque la replicación de sesiones existe en todas las pilas tecnológicas, no hay una especificación relacionada. Estoy familiarizado con la JVM, así que aquí hay un par de opciones:
- Tomcat ofrece replicación de sesiones de forma nativa
- Hazelcast ofrece una solución en memoria agrupada que puedes integrar en diferentes niveles
- Spring Session es una capa de abstracción sobre soluciones específicas
Cuando los datos se replican en todos los nodos (o en un clúster remoto), podrías pensar que ya no necesitas sesiones persistentes. Es cierto si solo se tiene en cuenta la disponibilidad y no el rendimiento. Se trata de la localidad de los datos: obtener datos en el nodo actual es más rápido que obtenerlos desde otro lugar a través de la red.
Sesiones persistentes en Apache APISIX
Las sesiones persistentes son imprescindibles para cualquier balanceador de carga, proxy inverso y puerta de enlace API que se precie. Sin embargo, debo admitir que la documentación de Apache APISIX necesita un punto de entrada fácil sobre el tema.
Apache APISIX vincula una ruta a un upstream. Un upstream consiste en uno o más nodos. Cuando una solicitud coincide con la ruta, Apache APISIX debe elegir entre todos los nodos disponibles para reenviar la solicitud. Por defecto, el algoritmo es round-robin ponderado. Round-robin usa un nodo tras otro, y después del último, vuelve al primero. Con un round-robin ponderado, el peso afecta cuántas solicitudes Apache APISIX reenvía a un nodo antes de cambiar al siguiente.
Sin embargo, hay otros algoritmos disponibles:
- Hash consistente
- Gráfico de media móvil ponderada exponencialmente
- Menos conexiones
- Uno personalizado
El hash consistente permite reenviar al mismo nodo dependiendo de algún valor: una variable de NGINX, una cabecera HTTP, una cookie, etc.
Recuerda que HTTP es un protocolo sin estado, por lo que los servidores de aplicaciones establecen una cookie en la primera respuesta para rastrear al usuario a través de las solicitudes HTTP. Es lo que llamamos una "sesión". Necesitamos conocer el nombre de la cookie de sesión subyacente. Diferentes servidores de aplicaciones entregan diferentes cookies:
JSESSIONID
para servidores basados en JVMPHPSESSID
para PHPASPSESSIONID
para ASP.Net- etc.
Usaré un Tomcat regular, por lo que la cookie de sesión es JSESSIONID
. Por lo tanto, la documentación de Apache APISIX para dos nodos es la siguiente:
routes:
- uri: /*
upstream:
nodes:
"tomcat1:8080": 1 #1
"tomcat2:8080": 1 #1
type: chash #2
hash_on: cookie #3
key: cookie_JSESSIONID #4
- Define los nodos del upstream
- Elige el algoritmo de hash consistente
- Hash basado en la cookie
- Define en qué cookie hacer el hash
Conclusión
En esta publicación, detallamos las sesiones persistentes, que siempre debes usar la replicación de sesiones junto con las sesiones persistentes, y cómo implementar sesiones persistentes en Apache APISIX.
Para profundizar: