Principios de Implementación Central del Centro de Registro de Nacos: Una Exploración Profunda

Al utilizar Nacos, es posible que surjan varias preguntas:

  • ¿Qué son las instancias temporales y permanentes y cuáles son sus diferencias?
  • ¿Cómo se registran las instancias de servicio en el servidor?
  • ¿Cómo mantienen la conexión las instancias de servicio y el servidor?
  • ¿Cómo se implementa la suscripción de servicios?
  • ¿Cómo se sincronizan los datos entre clústeres? ¿Se prioriza CP o AP?
  • ¿Cuál es el modelo de datos de Nacos?

Este artículo profundiza en los principios de implementación subyacentes del centro de registro de Nacos abordando estas cuestiones, cubriendo tanto la versión 1.x como la 2.x.

Instancias Temporales vs. Permanentes

El concepto de instancias temporales y permanentes es fundamental en Nacos. Sus implementaciones subyacentes difieren significativamente.

Instancias Temporales

Las instancias temporales se almacenan en una caché interna del servidor y no se persisten en disco. Cuando una instancia de servicio se vuelve inestable o se desconecta, se elimina del registro de servicios.

Instancias Permanentes

Las instancias permanentes se almacenan tanto en el registro de servicios como en archivos de disco. Cuando una instancia permanente se vuelve inestable, su estado de salud se marca como 'no saludable', pero no se elimina del registro. Esto permite ver su estado incluso cuando no está en óptimas condiciones.

Razón de la distinción:

  • Instancias Temporales: Ideales para servicios de negocio que no necesitan permanecer visibles en el registro una vez que se desconectan.
  • Instancias Permanentes: Adecuadas para servicios de infraestructura (como MySQL, Redis) que deben estar siempre disponibles y visibles, incluso si experimentan problemas temporales. Estas instancias pueden registrarse manualmente a través del SDK.

En entornos Spring Cloud, los servicios de negocio suelen registrarse como temporales por defecto. Para configurar instancias permanentes, se puede ajustar la siguiente propiedad:

spring:
  cloud:
    nacos:
      discovery:
        # Establecer en 'false' para instancias permanentes
        ephemeral: false

Diferencia clave entre Nacos 1.x y 2.x:

  • Nacos 1.x: Un servicio podía tener una mezcla de instancias temporales y permanentes. La determinación era a nivel de instancia.
  • Nacos 2.x: Todas las instancias de un servicio son o temporales o permanentes. La determinación es a nivel de servicio, lo que es más lógico para servicios como MySQL donde todas las instancias son inherentemente permanentes. Esto lleva a la distinción entre "servicios temporales" y "servicios permanentes".

Registro de Servicios

El registro de servicios es una funcionalidad principal donde las instancias de servicio envían sus metadatos (IP, puerto, etc.) al servidor de Nacos, que los almacena en el registro de servicios.

Implementación en Nacos 1.x

En Nacos 1.x, el registro de servicios se realiza a través de interfaces HTTP. Dada la naturaleza de Spring Boot de Nacos, esta implementación es relativamente sencilla.

Implementación en Nacos 2.x

Nacos 2.x introduce cambios significativos, principalmente en el protocolo de comunicación.

Cambio en el Protocolo de Comunicación

La principal actualización es el cambio del protocolo HTTP en 1.x a gRPC en 2.x para la comunicación cliente-servidor. gRPC, un framework RPC de alto rendimiento, utiliza Netty en su implementación Java y reduce la sobrecarga de crear y destruir conexiones HTTP con frecuencia, mejorando el rendimiento del registro hasta dos veces.

A pesar del cambio a gRPC, Nacos 2.x conserva las interfaces de registro HTTP para mantener la compatibilidad con SDKs de Nacos 1.x.

Implementación Detallada

Al iniciarse, el cliente de Nacos establece una conexión persistente con el servidor a través de gRPC. Todas las comunicaciones posteriores se realizan sobre esta conexión.

Para las instancias temporales, Nacos 2.x también almacena la información de la instancia de servicio en una caché local del cliente. Esto habilita la operación "Redo", un mecanismo de compensación que se ejecuta periódicamente (cada 3 segundos por defecto). Si la conexión se interrumpe y se restablece, la operación Redo asegura que las instancias de servicio registradas previamente se vuelvan a registrar en el servidor.

Este mecanismo Redo es crucial no solo para el registro, sino también para otras operaciones como la suscripción de servicios, asegurando que se repitan cuando se restablece la conexión.

Mecanismo de Latidos (Heartbeat)

El mecanismo de latidos, también conocido como mecanismo de mantenimiento de vida, permite a las instancias de servicio notificar al centro de registro que siguen activas. En caso de cierre normal, la instancia envía una solicitud de baja. Sin embargo, en escenarios anómalos (como problemas de red), el servidor necesita una forma de detectar instancias no disponibles.

Importante: El mecanismo de latidos en Nacos se aplica únicamente a instancias temporales.

Implementación de Latidos en Nacos 1.x

En Nacos 1.x, los latidos se implementan mediante tareas programadas tanto en el cliente como en el servidor.

  • Cliente: Inicia una tarea programada cada 5 segundos para enviar latidos (información de la instancia) al servidor mediante HTTP.
  • Servidor: Una tarea programada (también cada 5 segundos) verifica la hora del último latido de cada instancia.
    • Si el último latido supera los 15 segundos pero no los 30 segundos, la instancia se marca como 'no saludable'.
    • Si el último latido supera los 30 segundos, la instancia se elimina del registro de servicios.

Curiosamente, el mecanismo de latidos en 1.x también funciona como un mecanismo Redo. Si el servidor recibe un latido para una instancia que no está en su registro, la agrega, logrando un efecto de re-registro similar al Redo en 2.x.

Implementación de Latidos en Nacos 2.x

Debido al cambio a gRPC y las conexiones persistentes, Nacos 2.x aprovecha el mecanismo de latidos inherente a la conexión gRPC. Si la conexión se interrumpe, el servidor asume que las instancias de servicio registradas a través de esa conexión ya no están disponibles y las elimina del registro.

Además, Nacos 2.x introduce un mecanismo de detección proactiva en el servidor. Una tarea programada (cada 3 segundos por defecto) escanea las conexiones que no han tenido actividad en más de 20 segundos. Si se detecta una conexión inactiva, el servidor envía una solicitud al cliente. Si la solicitud falla, el servidor considera la conexión anómala y elimina las instancias de servicio asociadas.

En resumen, Nacos 2.x utiliza dos mecanismos para el mantenimiento de vida:

  • El latido de la conexión gRPC (la desconexión elimina la instancia).
  • La detección proactiva del servidor (elimina instancias de conexiones inactivas).

Verificación de Salud (Health Check)

Mientras que los latidos son para instancias temporales, las instancias permanentes (como MySQL) no pueden enviar latidos activamente. Para ellas, Nacos utiliza un mecanismo de verificación de salud.

A diferencia de los latidos (empuje del cliente), la verificación de salud implica que el servidor solicita activamente inofrmación sobre el estado de la instancia.

La implementación de la verificación de salud es similar en Nacos 1.x y 2.x. El servidor ejecuta una tarea programada (con intervalos de 2000-7000 ms) para verificar la salud de las instancias. Los métodos de verificación incluyen:

  • TCP: Verifica la conectividad de la instancia a través de su IP y puerto.
  • HTTP: Envía una solicitud HTTP a una ruta configurada en la instancia. Una respuesta exitosa indica que está saludable.
  • MySQL: Ejecuta una consulta SQL específica para verificar el estado (por ejemplo, si es una réplica maestra).

Por defecto, se utiliza la verificación TCP.

Descubrimiento de Servicios

El descubrimiento de servicios permite a otros servicios encontrar las instancias de servicio registradas. Nacos ofrece dos modos:

  • Consulta Activa (Pull): El cliente consulta activamente al servidor por instancias de servicio.
  • Suscripción de Servicios (Push): El cliente se suscribe a un servicio, y el servidor le notifica proactivamente sobre los cambios en las instancias de servicio. Este es el moddo preferido y predeterminado en la integración con Spring Cloud.

Implementación de la Consulta de Servicios

La consulta es sencilla en ambas versiones: Nacos 1.x usa solicitudes HTTP, mientras que Nacos 2.x utiliza solicitudes gRPC. El servidor busca en su registro de servicios y devuelve las instancias que coinciden con los criterios.

Implementación de la Suscripción de Servicios

La suscripción se inicia a través del método NamingService#subscribe en el SDK. Cuando los datos de las instancias de servicio cambian, se invoca un EventListener para recibir los datos actualizados.

Suscripción en Nacos 1.x

  1. Inicio: El cliente crea una clase PushReceiver que utiliza un socket UDP (con un puerto aleatorio) para recibir datos del servidor.
  2. Suscripción: Al llamar a NamingService#subscribe, el cliente primero consulta todas las instancias del servicio suscrito al servidor. El puerto UDP se envía al servidor, que lo utiliza para enviar actualizaciones de instancias de servicio al cliente. Los datos de las instancias se almacenan en una caché interna del cliente.
  3. Actualización Programada: Se inicia una tarea programada (con un intervalo de 10 segundos, devuelto por el servidor) para consultar periódicamente las instancias del servicio suscrito y actualizar la caché interna. Esto sirve como un mecanismo de respaldo debido a la naturaleza no confiable de la comunicación UDP.

Suscripción en Nacos 2.x

Nacos 2.x abandona el uso de UDP para las notificaciones de cambio de servicio. En su lugar, utiliza la conexión persistente gRPC. El servidor envía directamente los cambios de servicio al cliente a través de esta conexión.

  • Procesamiento: El cliente actualiza su caché interna de manera similar a la versión 1.x.
  • Mecanismo de Comparación Programada: Se mantiene el mecanismo de comparación programada, pero está desactivado por defecto, asumiendo la estabilidad de las conexiones gRPC. Si la conexión se restablece, la operación Redo garantiza la obtención de los datos más recientes.

Nota importante: En Nacos 1.x, todos los servicios podían ser suscritos. En Nacos 2.x, solo se admiten servicios temporales para la suscripción.

Consistencia de Datos

Dado que Nacos soporta modo clúster, la consistencia de datos en un sistema distribuido es una preocupación clave.

Mecanismo de Responsabilidad de Instancias de Servicio

En un clúster de Nacos, para distribuir la carga, cada nodo de Nacos solo gestiona un subconjunto de instancias de servicio para tareas como la monitorización de latidos y la verificación de salud. Este es el "mecanismo de responsabilidad", donde cada nodo de Nacos es responsable de un conjunto específico de instancias, aunque todos los nodos mantienen una copia completa del registro de servicios.

Teorema CAP y Teoría BASE

  • Teorema CAP: En un sistema distribuido, solo se pueden satisfacer dos de tres garantías: Consistencia (C), Disponibilidad (A) y Tolerancia a Particiones (P). Dado que la tolerancia a particiones es esencial en sistemas distribuidos, la elección se reduce a Consistencia o Disponibilidad.
  • Teoría BASE: Representa un compromiso en sistemas distribuidos: Basic Availability (Disponibilidad Básica), Soft State (Estado Blando) y Eventually Consistent (Consistencia Eventual). Prioriza la disponibilidad sobre la consistencia inmediata, asegurando que los datos converjan a un estado consistente con el tiempo.

AP vs. CP en Nacos

Nacos soporta tanto AP como CP, dependiendo de la funcionalidad específica:

  • Instancias Temporales: Nacos prioriza la Disponibilidad (AP) para el registro de instancias temporales.
  • Instancias Permanentes: Nacos prioriza la Consistencia (CP) para el registro de instancias permanentes.

Implementación AP de Nacos

Utiliza el protocolo Distro desarrollado internamente. Todos los nodos del servidor son iguales y pueden manejar solicitudes de lectura/escritura. Al iniciarse, un nodo obtiene todos los datos del servicio de otro nodo del clúster.

Para registrar instancias temporales, un nodo no solo las almacena localmente sino que también las sincroniza con todos los demás nodos del clúster. Si la sincronización falla para algunos nodos, el clúster sigue siendo disponible (AP). Los mecanismos para asegurar la consistencia eventual incluyen:

  • Reintento de Fallos: Se reintentan las sincronizaciones fallidas cada 3 segundos.
  • Comparación Programada: Los nodos periódicamente intercambian números de versión de los datos de servicio que gestionan. Si se detectan discrepancias, se sincronizan los datos más recientes.

Implementación CP de Nacos

Se basa en el algoritmo Raft. En Nacos 2.x, se utiliza el framework JRaft de Ant Financial (anteriormente implementado manualmente en 1.x).

En Raft, los nodos pueden ser Líder (maneja todas las escrituras), Seguidor (replica datos del líder) o Candidato (durante la elección del líder). El algoritmo asegura que una escritura solo se confirma después de que más de la mitad de los seguidores la hayan replicado exitosamente. Esto garantiza la consistencia (CP), ya que las escrituras fallan si no se alcanza el quórum.

Detallle importante: Si bien Raft prescribe que las lecturas también deben provenir del líder para una consistencia estricta, Nacos 2.x (al menos para la lectura de instancias de servicio) permite que los seguidores manejen solicitudes de lectura directamente de su estado local. Esto puede llevar a una inconsistencia temporal si un seguidor no ha replicado la última escritura del líder. (JRaft ofrece optimizaciones para lecturas consistentes desde seguidores).

Modelo de Datos

Un servicio en Nacos se identifica de forma única por tres componentes:

  • Namespace: Para aislamiento multi-inquilino (por defecto: public).
  • Group: Para aislamiento de entornos (por defecto: DEFAULT_GROUP).
  • ServiceName: El nombre del servicio.

Al registrar o suscribir servicios, se deben especificar estos componentes; de lo contrario, Nacos utilizará los valores predeterminados.

Además, existe el concepto de Cluster dentro de un servicio. Las instancias de servicio pueden asignarse a un clúster específico (por defecto: DEFAULT). Esto se puede configurar mediante:

spring:
  cloud:
    nacos:
      discovery:
        cluster-name: sanyoujavaCluster

La suscripción a servicios también puede filtrar por clúster, permitiendo, por ejemplo, priorizar las llamadas de servicio a instancias dentro de la misma región geográfica para mejorar el rendimiento.

Etiquetas: nacos Registro de Servicios descubrimiento de servicios gRPC Raft

Publicado el 7-23 08:56