Analyse du code source de RocketMQ——NameServer

Pourquoi devriez-vous apprendre le code source de RocketMQ ?

  • Écrivez du code élégant et efficace. En tant que produit de liaison principal d'Alibaba pour les transactions Double Eleven, RocketMQ prend en charge des dizaines de millions de simultanéités et des milliards de pics de données. La lecture du code source peut accumuler de l’expérience dans l’écriture de code efficace et élégant.
  • Améliorez les capacités de conception micro-architecturale, en vous concentrant sur la réflexion et les concepts. En tant que projet Apache de haut niveau, la conception architecturale d'Apache RocketMQ mérite d'être étudiée.
  • Résolvez diverses maladies difficiles et compliquées au travail et aux études. Si vous rencontrez des problèmes tels qu'une consommation bloquée ou un retard lors de l'utilisation de RocketMQ, vous pouvez trouver le problème et le résoudre en lisant le code source.
  • Montrez votre excellence lors d’entretiens avec les sociétés Internet de premier rang BATJ. Lors d’entretiens avec de grandes entreprises, notamment des sociétés basées sur Alibaba, ce sera certainement un gros plus si vous avez une connaissance systématique du code source de RocketMQ.

Points forts techniques du code source de RocketMQ

  • verrouillage en lecture-écriture
  • Classe d'opération atomique
  • Conception du stockage de fichiers
  • Zéro copie : MMAP
  • Pool de threads
  • ConcurrentHashMap
  • Conteneurs de copie sur écriture
  • Stratégie d'équilibrage de charge
  • Mécanisme de retard de défaillance
  • mémoire hors tas

Structure du module RocketMQ

Le module global de RocketMQ est le suivant :

  1. rocketmq-namesrv : service de noms. Mettre à jour et acheminer les services du courtier de découverte. Fournissez aux producteurs et aux consommateurs de messages des informations de routage sur les sujets. En plus de stocker les informations de routage de base, NameServer doit également être capable de gérer les nœuds Broker, y compris l'enregistrement du routage, la suppression du routage et d'autres fonctions.
  2. rocketmq-broker : Le noyau de mq. Il peut recevoir des demandes de producteurs et de consommateurs et appeler les services de la couche magasin pour traiter les messages. L'unité de base du service HA prend en charge les modes double écriture synchrone, double écriture asynchrone et autres.
  3. rocketmq-store : implémentation de la couche de stockage, y compris la mise en œuvre du service d'indexation et du service HA haute disponibilité.
  4. rocketmq-remoting : L'implémentation de communication sous-jacente basée sur netty, toutes les interactions entre les services sont basées sur ce module.
  5. rocketmq-common : Certaines classes fonctionnelles communes entre les modules, telles que certains fichiers de configuration et constantes.
  6. rocketmq-client : version Java de l'implémentation du client mq
  7. rocketmq-filter : Service de filtrage des messages, qui équivaut à l'ajout d'un agent de filtrage entre le courtier et le consommateur.
  8. rocketmq-srvutil : ServerUtil, une classe d'outils pour analyser les lignes de commande.
  9. rocketmq-tools : outil de gestion de cluster mq, fournissant des fonctions telles que la requête de messages

RocketMQ a beaucoup de code source. Il n'est pas nécessaire de lire tout le code source de RocketMQ. Interpréter le code source principal et clé. Le processus de base de RocketMQ est le suivant :

  • Processus de démarrage
    Le serveur RocketMQ se compose de deux parties : NameServer et Broker. NameServer est le centre d'enregistrement du service. Le courtier enregistrera son adresse sur NameServer. Lorsque le producteur et le consommateur démarrent, ils obtiendront d'abord l'adresse du courtier auprès de NameServer, puis accéderont à à partir de NameServer. Le courtier envoie et reçoit des messages.
  • Le processus de production de messages
    Producer écrit le message dans la file d'attente spécifique du courtier du cluster RocketMQ.
  • Le processus de consommation de messages
    Comsumer extrait le message correspondant du cluster RocketMQ et confirme la consommation.

Analyse du code source du serveur de noms

Processus global du serveur de noms

NameServer est le "cerveau" de l'ensemble de RocketMQ. C'est le centre d'enregistrement des services de RocketMQ, donc RocketMQ doit d'abord démarrer le NameServer, puis démarrer le Broker dans Rocket.

Insérer la description de l'image ici

  • NameServer démarre.
    Commencez à écouter et attendez les connexions Broker, Producer et Comsumer. Le courtier s'enregistre auprès de tous les serveurs de noms au démarrage. Le producteur obtient la liste d'adresses du serveur du courtier du serveur de noms avant d'envoyer des messages, puis sélectionne un serveur dans la liste pour envoyer des messages en fonction de l'algorithme d'équilibrage de charge. Le consommateur obtient la liste d'adresses du serveur Broker (éventuellement un cluster) du NamerServer avant de s'abonner au message d'une rubrique, mais le consommateur choisit de s'abonner au message du Broker. Les règles d'abonnement sont déterminées par la configuration du Broker.
  • Une fois le courtier d'enregistrement de routage
    démarré, il envoie des informations de routage et de pulsation à tous les serveurs de noms.
  • Route Elimination
    NameServer maintient une longue connexion avec chaque service Broker et vérifie si le Broker est actif toutes les secondes 10. S'il détecte que le Broker est en panne, il sera supprimé du registre de routage. De cette manière, la haute disponibilité de RocketMQ peut être obtenue.

Processus de démarrage du serveur de noms

NameServer est démarré séparément. Classe d'entrée : NamesrvController. L'organigramme est le suivant :

image.png

Charger la configuration KV

Interprétation de base de createNamesrvController() dans la classe NamesrvController

image.png

On constate qu'il y a un paramètre p dans le code source. Si vous entrez directement -p dans le paramètre de démarrage, vous pouvez imprimer toutes les informations sur les paramètres du NameServer (mais le NameServer se terminera automatiquement), indiquant que ce -p est un paramètre de test.

image.png

Lors d'un démarrage normal, tous les paramètres se trouvent dans le journal de démarrage :

image.png

Construire une communication NRS pour recevoir des informations de routage et de battement de cœur

image.png

image.png

Les tâches planifiées éliminent les délais d'attente Broker

Le contrôleur principal lancera une tâche planifiée : analyser les courtiers toutes les 10 secondes et supprimer les courtiers inactifs.

Le Broker envoie un paquet de pulsations au NameServer toutes les 30 secondes. Le paquet de pulsations contient le BrokerId, l'adresse du courtier, le nom du courtier, le nom du cluster auquel le courtier appartient et la liste des FilterServers associés au courtier.

image.png

Mais si le Broker tombe en panne et que le NameServer ne peut pas recevoir le paquet de battements de cœur, comment le NameServer élimine-t-il ces Brokers défaillants ? NameServer analysera la table d'état de BrokerLiveTable toutes les secondes 10. Si l'horodatage du lastUpdateTimestamp de BrokerLive est supérieur à 120 secondes de l'heure actuelle, le courtier sera considéré comme invalide, le courtier sera supprimé, la connexion avec le courtier sera fermée et topicQueueTable , BrokerAddrTable, BrokerLiveTable et filterServerTable seront mis à jour en même temps.

image.png

Cependant, cette conception présente des problèmes : si le Broker que le NameServer pense être disponible est en réalité en panne, les routes lues depuis le NameServer incluent des hôtes indisponibles, ce qui entraînera une production/consommation anormale de messages. Ce problème peut être résolu par des stratégies d’évitement des fautes et des mécanismes de nouvelle tentative du côté de la production et du consommateur. Cette conception est conforme à la philosophie de conception de RocketMQ : la conception globale recherche la simplicité et les performances. Dans le même temps, le NameServer est conçu pour être sans état et plusieurs serveurs peuvent être déployés à volonté. Le code est également très simple et léger.

RocketMQ dispose de deux points de déclenchement pour supprimer les informations de routage :

  • NameServer analyse périodiquement le brokerLiveTable pour détecter la différence de temps entre le dernier paquet de battement de cœur et le système actuel. Si le temps dépasse 120 s, le courtier doit être supprimé.
  • Lorsque le Broker est arrêté normalement, il exécutera la commande unregisterBroker. Les deux méthodes de suppression de routage sont les mêmes et toutes deux suppriment les informations relatives au courtier de la table de routage correspondante.

Une fois que le consommateur a démarré, la première étape consiste à obtenir des informations relatives au sujet auprès du serveur de noms.

Points forts de la conception du serveur de noms

verrouillage en lecture-écriture

Il existe une conception de verrouillage en lecture-écriture dans la classe RouteInfoManager

image.png

Lorsqu'un message est envoyé, le client obtiendra les informations de routage du NameServer et le Broker mettra régulièrement à jour les informations de routage du NameServer, de sorte que la table de routage effectuera très fréquemment les opérations suivantes :

  1. Lorsque les producteurs envoient des messages, ils doivent fréquemment obtenir des sujets et lire le tableau des sujets.
    image.png
  2. Le courtier mettra régulièrement à jour une table de routage (30 s) et écrira dans la table Topic.
    image.png

Comment une lecture et une écriture fréquentes peuvent-elles améliorer la simultanéité, en particulier lorsque les producteurs envoient des messages, c'est pourquoi le mécanisme de verrouillage en lecture-écriture est utilisé ici (pour les scénarios où il y a plus de lecture et moins d'écriture).

Synchronized et ReentrantLock sont essentiellement des verrous exclusifs. Les verrous exclusifs permettent à un seul thread d'accéder en même temps, tandis que les verrous en lecture-écriture peuvent permettre à plusieurs threads de lecture d'accéder en même temps. Cependant, lorsqu'un thread d'écriture accède, tous les threads de lecture et d'autres auteurs Les discussions sont bloquées. Le verrou en lecture-écriture maintient une paire de verrous, un verrou en lecture et un verrou en écriture. En séparant le verrou en lecture et le verrou en écriture, la concurrence est grandement améliorée par rapport au verrou exclusif général.

Le stockage est basé sur la mémoire

NameServer stocke les informations suivantes :

topicQueueTable : informations de routage de la file d'attente de messages du sujet, l'équilibrage de charge est effectué en fonction de la table de routage lors de l'envoi des messages.

brokerAddrTable : informations de base du courtier, y compris le nom du courtier, le nom du cluster, les adresses du courtier actif et de sauvegarde

clusterAddrTable : informations sur le cluster de courtier, stocke tous les noms de courtier dans le cluster

brokerLiveTable : informations sur l'état du courtier, NameServer remplacera ces informations à chaque fois qu'il recevra un paquet de battements de cœur.

filterServerTable : liste FilterServer sur le Broker, utilisée pour le filtrage des messages en mode classe.

image.png

L'implémentation de NameServer est basée sur la mémoire. NameServer ne conserve pas les informations de routage. La tâche importante de persistance est laissée au Broker. Cette conception peut améliorer les capacités de traitement de NameServer.

Serveur de noms sans état

  • Ils ne communiquent pas entre eux dans le cluster NameServer.
  • Dans l'architecture maître-esclave, le courtier enregistrera les informations de routage et de pulsation auprès de tous les serveurs de noms.
  • Le producteur/consommateur établit simultanément une longue connexion avec l'un des clusters NameServer.

Supposons qu'un cluster RocketMQ soit déployé dans deux salles informatiques. Chaque salle informatique possède des nœuds NameServer, Broker et client. Lorsque le lien entre les deux salles informatiques est interrompu, tous les serveurs NameServers peuvent fournir des services et le client ne peut être que dans le local. salle informatique. Recherchez le courtier de cette salle informatique dans NameServer.

Dans le cluster RocetMQ, les NameServers n'ont pas besoin de communiquer entre eux, les partitions réseau n'ont donc aucun impact sur la disponibilité du NameServer lui-même. Si le NameServer détecte que la connexion au Broker est interrompue, le NameServer pensera que le Broker peut ne fournit plus de services et le NameServer Ce Broker sera immédiatement supprimé des informations de routage pour empêcher le client de se connecter à un Broker indisponible.

Une fois le réseau partitionné, le NameServer ne peut pas recevoir les battements de cœur des Brokers dans la salle informatique homologue. À ce stade, chaque Namesever ne dispose que des informations Broker de la salle informatique locale.

Je suppose que tu aimes

Origine blog.csdn.net/qq_28314431/article/details/133030933
conseillé
Classement