Analyse du code source RocketMQ : comment résoudre les problèmes de perte de messages ?

Veuillez ajouter une description de l'image

Comment résoudre les problèmes de perte de message ?

Lorsque nous utilisons mq, nous rencontrons souvent le problème de la consommation anormale de messages. Il existe de nombreuses raisons, telles que

  1. échec de l'envoi du producteur
  2. Exception de consommation
  3. le consommateur n'a pas du tout reçu le message

Alors, comment enquêter ?


insérez la description de l'image ici
En fait, avec l'aide de RocketMQ -Dashboard, vous pouvez vérifier efficacement, il existe de nombreuses fonctions que vous ne pouvez pas imaginer

Message non trouvé?

Cela signifie que le proder envoie anormalement, ou que le message est expiré, car le message rocketmq est enregistré pendant 72h par défaut, à ce moment, allez dans le journal du producteur pour une confirmation supplémentaire.

Message trouvé !

Ensuite, regardez l'état de consommation du message, comme indiqué dans la figure ci-dessous, l'état de consommation du message est NOT_ONLINE

insérez la description de l'image ici
Que signifie NOT_ONLINE ?

Ne vous inquiétez pas, analysons-le étape par étape, voyons combien d'états possède TrackType.

public enum TrackType {
    
    
    CONSUMED,
    CONSUMED_BUT_FILTERED,
    PULL,
    NOT_CONSUME_YET,
    NOT_ONLINE,
    UNKNOWN
}

Chaque type est expliqué ci-dessous

Types de Explique
CONSOMMÉ le message a été consommé
CONSOMMÉ_MAIS_FILTRÉ Le message a été livré mais filtré
TIRER Le mode de consommation des messages est le mode pull
NOT_CONSUME_YET pas consommé actuellement
PAS EN LIGNE CONSUMER est hors ligne
INCONNU erreur inconnue

Comment déterminer que le message a été consommé ?

Comme nous l'avons mentionné dans la section précédente, le courtier utilisera une carte pour enregistrer la progression de la consommation de chaque file d'attente. Si l'offset de la file d'attente est supérieur à l'offset du message interrogé, le message sera consommé, sinon il ne sera pas consommé (NOT_CONSUME_YET)

Est-il possible de savoir immédiatement d'où vient le problème ?

CONSUMED_BUT_FILTERED indique que le message a été livré, mais a été filtré . Par exemple, le producteur envoie topicA, tagA, mais le consommateur s'abonne à topicA, tagB

Sur RocketMQ-Dashboard, nous pouvons en fait voir le décalage (site du courtier) de chaque courtier de file d'attente et le décalage (site consommateur) de la consommation de messages. La différence correspond aux messages qui ne sont pas consommés.
insérez la description de l'image ici
Lorsque tous les messages sont consommés, la différence est de 0 , comme le montre la figure ci-dessous

insérez la description de l'image ici
Comment CONSUMED_BUT_FILTERED (message livré mais filtré) se produit-il ?

Cela doit mentionner un concept dans RocketMQ. La consommation de messages doit respecter la cohérence de la relation d'abonnement, c'est-à-dire que les sujets et les balises souscrits par tous les consommateurs d'un consumerGroup doivent être cohérents, sinon les messages seront perdus.

Comme illustré dans le scénario suivant, 4 messages sont envoyés, consommateur1 s'abonne à topica-taga et consommateur2 s'abonne à topica-tab. consommateur1 consomme des données en q0, consommateur2 consomme des données en q1

Pour msg-1 et msg-3 livrés à q0, seul msg-1 peut être consommé normalement, tandis que msg-3 est CONSUMED_BUT_FILTERED. Parce que msg-3 est livré à q0, mais que consumer1 ne consomme pas le message de tagb, le message est filtré et le message est perdu

De même msg-2 ce message sera également perdu
insérez la description de l'image ici

Notez qu'il y a un autre point très important

Bien que la consommation du message échoue, le décalage du message sera soumis normalement, c'est-à-dire que la consommation du message échoue, mais le statut sera également CONSOMMÉ

Alors, où est passée la nouvelle de l'échec de la consommation ?

Lorsque la consommation du message échoue, il sera placé dans la file d'attente des nouvelles tentatives et le nom du sujet est %RETRY% + consumerGroup

Le consommateur n'est pas abonné à ce sujet, comment peut-il consommer les messages de nouvelle tentative ?
insérez la description de l'image ici
En fait, lorsque le consommateur démarre, le framework s'abonne à ce sujet pour vous, de sorte que le message de nouvelle tentative peut être consommé pour

De plus, le message n'est pas réessayé tout le temps, mais toutes les 1 périodes de temps.

nombre de fois pour réessayer intervalle de temps depuis la dernière tentative nombre de fois pour réessayer intervalle de temps depuis la dernière tentative
1 10 secondes 9 7 minutes
2 30 secondes dix 8 minutes
3 1 minute 11 9 minutes
4 2 minutes 12 10 minutes
5 3 minutes 13 20 minutes
6 4 minutes 14 30 minutes
7 5 minutes 15 1 heure
8 6 minutes 16 2 heures

Lorsque le message dépasse les temps de consommation maximum de 16 fois, le message sera remis à la file d'attente de lettres mortes. Le nom de sujet de la file d'attente de lettres mortes est %DLQ% + consumerGroup.

Par conséquent, lorsque vous constatez que l'état du message est CONSOMMÉ, mais que la consommation échoue, accédez simplement à la file d'attente des nouvelles tentatives et à la file d'attente des lettres mortes pour le trouver.

Dépannage des exceptions de consommation de messages

Le contexte de ce problème est le suivant, c'est-à-dire que nous avons deux systèmes, et la cohérence des données est assurée par mq au milieu. Du coup, un jour, les données sont incohérentes, il doit y avoir un problème avec le consommateur qui consomme des messages, ou le producteur envoyant des messages.

Trouvez d'abord le message en fonction de la période de temps pour vous assurer qu'il n'y a pas de problème d'envoi, puis voyez que le statut du message est NOT_CONSUME_YET, indiquant que le consommateur est en ligne mais qu'il n'y a pas de message

Veuillez ajouter une description de l'image
NOT_CONSUME_YET indique que le message n'a pas été consommé , mais cela fait longtemps que le message n'a pas été envoyé. Le consommateur ne devrait pas l'avoir consommé. Vérifiez dans le journal que le consommateur ne l'a pas consommé.

Utilisez RocketMQ-Dashboard pour vérifier le site de l'agent et le site du consommateur.La file d'attente 0 consomme normalement et les autres files d'attente ne sont pas consommées.Je
insérez la description de l'image ici
pense que cette stratégie d'équilibrage de charge est un peu problématique, pourquoi il y a tant de messages dans la file d'attente 0, et pourquoi il n'y a pas de messages dans d'autres files d'attente, demandez à une vague d'étudiants en middleware, ont-ils encore changé la stratégie d'équilibrage de charge ?

C'est vrai que ça a changé ! Dans l'environnement de test, la latitude de la file d'attente est utilisée pour distinguer plusieurs environnements. 0 est l'environnement de référence. Notre équipe n'a pas encore utilisé plusieurs environnements, donc les messages envoyés et reçus seront dans la file d'attente 0, et les autres files d'attente ne seront pas utilisées ( vous pouvez simplement penser que l'environnement de test envoie et consomme Le message n'utilisera que la file d'attente 0 )

Alors voici le problème !

Tout d'abord, le statut du message est NOT_CONSUME_YET, ce qui signifie que le message doit avoir été livré à la file d'attente 0, mais le partenaire middleware a déclaré que le message ne serait pas livré à la file d'attente 0.

Pour vérifier mon idée, nous devons d'abord prouver que les messages qui n'ont pas été consommés sont bien livrés à des files d'attente autres que la file d'attente 0.

Je ne parlerai pas des détours au milieu, jusqu'à ce que j'aie regardé le code source de RocketMQ-Dashboard et que j'ai constaté que Dashboard renvoyait en fait beaucoup d'informations sur le message, mais il n'était pas affiché sur la page. l'interface et retourna à
insérez la description de l'image ici
darling, et trouva un nouveau monde, news Toutes les propriétés de .sont ici, et vu que le queueId est 14, ça a vraiment vérifié mon idée.

Voyons que bornHost est en fait le segment réseau de notre bureau

La stratégie d'équilibrage de charge est-elle démarrée localement et la stratégie d'équilibrage de charge de l'environnement de test est-elle différente ?

Une vague de code de débogage local, il s'avère que le producteur local enverra des messages à toutes les files d'attente, et le consommateur consommera également des messages de toutes les files d'attente

Pour l'instant le problème a été trouvé !

Le producteur démarre un service localement, s'enregistre auprès du zk de l'environnement de test, certaines requêtes de l'environnement de test sont envoyées au local et des messages sont envoyés aux files d'attente autres que la file d'attente 0, mais le consommateur de l'environnement de test ne fera que consommer les messages dans la file d'attente 0, ce qui entraîne Le message n'a pas été consommé depuis longtemps

paramètre

[1]http://www.broadview.com.cn/article/419768
[2]https://mp.weixin.qq.com/s/wWgAbFLuesdb3BhY3GjxPg

Je suppose que tu aimes

Origine blog.csdn.net/zzti_erlie/article/details/123558837
conseillé
Classement