Análisis del código fuente de RocketMQ——NameServer

¿Por qué debería aprender el código fuente de RocketMQ?

  • Escriba código elegante y eficiente. Como producto de enlace principal de Alibaba para transacciones de Double Eleven, RocketMQ admite decenas de millones de concurrencias y billones de picos de datos. La lectura del código fuente puede acumular experiencia en la escritura de código eficiente y elegante.
  • Mejorar las capacidades de diseño microarquitectónico, centrándose en el pensamiento y los conceptos. Como proyecto Apache de alto nivel, vale la pena aprender del diseño arquitectónico de Apache RocketMQ.
  • Resuelve diversas enfermedades difíciles y complicadas en el trabajo y el estudio. Si encuentra problemas como consumo estancado o retrasos mientras usa RocketMQ, puede encontrar el problema y resolverlo leyendo el código fuente.
  • Muestre su excelente yo en entrevistas con empresas de Internet de primer nivel de BATJ. En entrevistas con empresas importantes, especialmente empresas con sede en Alibaba, definitivamente será una gran ventaja tener un conocimiento sistemático del código fuente de RocketMQ.

Aspectos técnicos destacados del código fuente de RocketMQ

  • bloqueo de lectura-escritura
  • Clase de operación atómica
  • Diseño de almacenamiento de archivos.
  • Copia cero: MMAP
  • Grupo de subprocesos
  • Mapa de hash concurrente
  • Contenedores de copia en escritura
  • Estrategia de equilibrio de carga
  • Mecanismo de retardo de falla
  • memoria fuera del montón

Estructura del módulo RocketMQ

El módulo general de RocketMQ es el siguiente:

  1. rocketmq-namesrv : servicio de nombres. Servicios de intermediario de actualización y descubrimiento de rutas. Proporcione a los productores y consumidores de mensajes información de enrutamiento sobre temas. Además de almacenar información de enrutamiento básica, NameServer también debe poder administrar los nodos Broker, incluido el registro de enrutamiento, la eliminación de enrutamiento y otras funciones.
  2. rocketmq-broker : El núcleo de mq. Puede recibir solicitudes de productores y consumidores y llamar a servicios de la capa de almacenamiento para procesar mensajes. La unidad básica del servicio HA admite modos de escritura dual síncrona, escritura dual asíncrona y otros modos.
  3. rocketmq-store : implementación de la capa de almacenamiento, incluido el servicio de índice y la implementación del servicio HA de alta disponibilidad.
  4. rocketmq-remoting : La implementación de comunicación subyacente basada en netty, todas las interacciones entre servicios se basan en este módulo.
  5. rocketmq-common : algunas clases funcionales comunes entre módulos, como algunos archivos de configuración y constantes.
  6. rocketmq-client : versión Java de la implementación del cliente mq
  7. rocketmq-filter : Servicio de filtrado de mensajes, que equivale a agregar un agente de filtrado entre el corredor y el consumidor.
  8. rocketmq-srvutil : ServerUtil, una clase de herramienta para analizar líneas de comando.
  9. rocketmq-tools : herramienta de gestión de clústeres mq, que proporciona funciones como consulta de mensajes

RocketMQ tiene mucho código fuente. No es necesario leer todo el código fuente de RocketMQ. Interprete el código fuente principal y clave. El proceso central de RocketMQ es el siguiente:

  • El proceso de inicio
    del servidor RocketMQ consta de dos partes: NameServer y Broker. NameServer es el centro de registro del servicio. El Broker registrará su dirección en NameServer. Cuando el productor y el consumidor comiencen, primero obtendrán la dirección del Broker de NameServer y luego irán a desde NameServer. El broker envía y recibe mensajes.
  • El productor del proceso de producción de mensajes
    escribe el mensaje en la cola específica en el corredor en el clúster RocketMQ.
  • El proceso de consumo de mensajes
    Comsumer extrae el mensaje correspondiente del clúster RocketMQ y confirma el consumo.

Análisis del código fuente de NameServer

Proceso general de NameServer

NameServer es el "cerebro" de todo RocketMQ y es el centro de registro de servicios de RocketMQ, por lo que RocketMQ necesita iniciar NameServer primero y luego iniciar Broker en Rocket.

Insertar descripción de la imagen aquí

  • Se inicia NameServer.
    Comience a escuchar y espere las conexiones de Broker, Producer y Comsumer. El Broker se registra con todos los NameServers cuando se inicia. El productor obtiene la lista de direcciones del servidor Broker del NameServer antes de enviar mensajes y luego selecciona un servidor de la lista para enviar mensajes según el algoritmo de equilibrio de carga. El consumidor obtiene la lista de direcciones del servidor Broker (posiblemente un clúster) del NamerServer antes de suscribirse al mensaje de un tema, pero el consumidor elige suscribirse al mensaje del Broker. Las reglas de suscripción están determinadas por la configuración del Broker.
  • Una vez iniciado el
    Broker de registro de enrutamiento, envía información de enrutamiento y latidos a todos los NameServers.
  • Eliminación de rutas
    NameServer mantiene una conexión larga con cada servicio de Broker y verifica si el Broker está activo cada 10 segundos. Si detecta que el Broker está inactivo, se eliminará del registro de enrutamiento. De esta forma, se puede lograr la alta disponibilidad de RocketMQ.

Proceso de inicio del servidor de nombres

NameServer se inicia por separado. Clase de entrada: NamesrvController. El diagrama de flujo es el siguiente:

imagen.png

Cargar configuración KV

Interpretación principal de createNamesrvController() en la clase NamesrvController

imagen.png

Se encuentra que hay un parámetro p en el código fuente. Si ingresa directamente -p en el parámetro de inicio, puede imprimir toda la información de los parámetros del NameServer (pero el NameServer terminará automáticamente), lo que indica que este -p es un parámetro de prueba.

imagen.png

Durante el inicio normal, todos los parámetros se pueden encontrar en el registro de inicio:

imagen.png

Construir comunicación NRS para recibir información de enrutamiento y latidos.

imagen.png

imagen.png

Las tareas programadas eliminan el tiempo de espera del Broker

El controlador central iniciará una tarea programada: escanear los Brokers cada 10 segundos y eliminar los Brokers inactivos.

El Broker envía un paquete de latidos al NameServer cada 30 segundos, que contiene el BrokerId, la dirección del Broker, el nombre del Broker, el nombre del clúster al que pertenece el Broker y la lista de FilterServers asociados con el Broker.

imagen.png

Pero si el Broker deja de funcionar y el NameServer no puede recibir el paquete de latidos, ¿cómo elimina el NameServer a estos Brokers fallidos? NameServer escaneará la tabla de estado de brokerLiveTable cada 10 segundos. Si la marca de tiempo de lastUpdateTimestamp de BrokerLive está a más de 120 segundos de la hora actual, el Broker se considerará inválido, el Broker se eliminará, la conexión con el Broker se cerrará y topicQueueTable , brokerAddrTable, brokerLiveTable y filterServerTable se actualizarán al mismo tiempo.

imagen.png

Sin embargo, hay problemas con este diseño. Si el Broker que NameServer cree que está disponible en realidad no funciona, las rutas leídas desde NameServer incluirán hosts no disponibles, lo que provocará una producción/consumo anormal de mensajes. Este problema puede resolverse mediante estrategias para evitar fallas y mecanismos de reintento en los lados de producción y consumidor. Este diseño está en línea con la filosofía de diseño de RocketMQ: el diseño general busca simplicidad y rendimiento. Al mismo tiempo, NameServer está diseñado para ser sin estado y se pueden implementar múltiples servidores a voluntad. El código también es muy simple y liviano.

RocketMQ tiene dos puntos de activación para eliminar información de enrutamiento:

  • NameServer escanea periódicamente brokerLiveTable para detectar la diferencia de tiempo entre el último paquete de latidos y el sistema actual. Si el tiempo excede los 120 segundos, es necesario eliminar el corredor.
  • Cuando el Broker se apaga normalmente, ejecutará el comando unregisterBroker. Los dos métodos de eliminación de enrutamiento son los mismos y ambos eliminan la información relacionada con el corredor de la tabla de enrutamiento relevante.

Una vez que el consumidor comienza, el primer paso es obtener información relacionada con el tema del NameServer.

Aspectos destacados del diseño de NameServer

bloqueo de lectura-escritura

Hay un diseño de bloqueo de lectura y escritura en la clase RouteInfoManager

imagen.png

Cuando se envía un mensaje, el cliente obtendrá la información de enrutamiento del NameServer y el Broker actualizará periódicamente la información de enrutamiento del NameServer, por lo que la tabla de enrutamiento tendrá las siguientes operaciones con mucha frecuencia:

  1. Cuando los productores envían mensajes, necesitan obtener temas con frecuencia y leer la tabla de temas.
    imagen.png
  2. El corredor actualizará una tabla de enrutamiento periódicamente (30 segundos) y escribirá en la tabla de temas.
    imagen.png

¿Cómo pueden la lectura y escritura frecuentes mejorar la concurrencia, especialmente cuando los productores envían mensajes? Por eso, aquí se utiliza el mecanismo de bloqueo de lectura y escritura (para escenarios donde hay más lectura y menos escritura).

Synchronized y ReentrantLock son básicamente bloqueos exclusivos. Los bloqueos exclusivos solo permiten el acceso de un subproceso al mismo tiempo, mientras que los bloqueos de lectura y escritura pueden permitir el acceso de varios subprocesos de lectura al mismo tiempo. Sin embargo, cuando un subproceso de escritura accede, todos los subprocesos de lectura y Otros escritores Los hilos están bloqueados. El bloqueo de lectura y escritura mantiene un par de bloqueos, un bloqueo de lectura y un bloqueo de escritura. Al separar el bloqueo de lectura y el bloqueo de escritura, la concurrencia mejora enormemente en comparación con el bloqueo exclusivo general.

El almacenamiento se basa en la memoria.

NameServer almacena la siguiente información:

topicQueueTable : Información de enrutamiento de la cola de mensajes del tema, el equilibrio de carga se realiza en función de la tabla de enrutamiento al enviar mensajes.

brokerAddrTable : información básica del corredor, incluido el nombre del corredor, el nombre del clúster y las direcciones del corredor activo y de respaldo.

clusterAddrTable : información del clúster de corredores, almacena todos los nombres de los corredores en el clúster

brokerLiveTable : información del estado del corredor. NameServer reemplazará esta información cada vez que reciba un paquete de latidos.

filterServerTable : lista de FilterServer en el Broker, utilizada para el filtrado de mensajes en modo clase.

imagen.png

La implementación de NameServer se basa en la memoria. NameServer no conserva la información de enrutamiento. La importante tarea de persistencia se deja en manos del Broker. Este diseño puede mejorar las capacidades de procesamiento de NameServer.

Servidor de nombres sin estado

  • No se comunican entre sí en el clúster de NameServer.
  • En la arquitectura maestro-esclavo, el Broker registrará información de enrutamiento y latidos con todos los NameServers.
  • El productor/consumidor establece una conexión larga con uno de los clústeres de NameServer al mismo tiempo.

Supongamos que un clúster RocketMQ se implementa en dos salas de computadoras. Cada sala de computadoras tiene algunos nodos NameServer, Broker y cliente. Cuando se interrumpe el enlace entre las dos salas de computadoras, todos los NameServers pueden proporcionar servicios y el cliente solo puede estar en el local. sala de ordenadores Busque el Broker de esta sala de ordenadores en NameServer.

En el clúster RocetMQ, los NameServers no necesitan comunicarse entre sí, por lo que las particiones de red no tienen ningún impacto en la disponibilidad del NameServer en sí. Si el NameServer detecta que la conexión con el Broker está interrumpida, el NameServer pensará que el Broker puede ya no proporciona servicios, y NameServer Este Broker se eliminará inmediatamente de la información de enrutamiento para evitar que el cliente se conecte a un Broker no disponible.

Una vez particionada la red, el NameServer no puede recibir los latidos del Broker en la sala de computadoras del mismo nivel. En este momento, cada Namesever solo tiene la información del Broker de la sala de computadoras local.

Supongo que te gusta

Origin blog.csdn.net/qq_28314431/article/details/133030933
Recomendado
Clasificación