Maison  >  Article  >  Java  >  5 questions d'entretien Dubbo à haute teneur en or !

5 questions d'entretien Dubbo à haute teneur en or !

Java后端技术全栈
Java后端技术全栈avant
2023-08-17 16:04:161076parcourir

Aujourd'hui, je vous propose un article sur l'interaction Dubbo IO.

Cet article est écrit par un collègue. Il utilise des mots intéressants pour écrire des points de connaissances ennuyeux. C'est facile à comprendre et très intéressant, j'ai donc hâte de trouver l'autorisation de l'auteur et de le partager avec tout le monde :


Quelques questions intéressantes

Dubbo est un excellent framework RPC avec des modèles de threads complexes Dans cet article, l'auteur analyse l'ensemble du processus IO de Dubbo sur la base de mes connaissances superficielles. Avant de commencer, examinons d'abord les questions suivantes :

  • Une fois la méthode métier exécutée, le paquet de données est-il envoyé ?
  • Quelle est la différence dans les modèles de thread entre netty3 et netty4 ?
  • Le paquet de données atteint le tampon du socket du système d'exploitation, que s'est-il passé ?
  • Le journal généré par le fournisseur prend très peu de temps, mais le client expire. Comment pouvons-nous résoudre le problème ?
  • Le paquet de données est-il envoyé directement via un canal au niveau de la couche physique ?
  • Le fil d'affaires grand public en attente est activé. Condition, à quelle heure est-il réveillé ?
  • ...

Ensuite, l'auteur utilisera Dubbo2.5.3 comme consommateur et 2.7.3 comme fournisseur pour décrire l'ensemble du processus d'interaction. L'auteur se place dans la perspective du paquet de données et le raconte. à la première personne. Attachez votre ceinture.

Voyage intéressant

1. Dubbo2.5.3 Le consommateur lance une demande

Je suis un paquet de données, né dans une ville appelée Dubbo2.5.3 Consommateur, ma mission est de fournir des informations et j'apprécie également voyages.

Un jour, j'étais sur le point d'être envoyé. On a dit que j'allais à un endroit appelé Dubbo 2.7.3 Provider.

Ce jour-là, le fil métier a lancé un appel de méthode, dans FailoverClusterInvoker#doInvoke code> J'ai choisi un fournisseur, puis je suis passé par divers filtres grand public, puis par le pipeline Netty3, et enfin j'ai passé <code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius : 4px ;marge : 0 2px ;couleur d'arrière-plan : rgba(27,31,35,.05) ;famille de polices : Operator Mono, Consolas, Monaco, Menlo, monospace ;saut de mot : break-all ;couleur : # ff6441; ">NioWorker#scheduleWriteIfNecessary, je suis arrivé à la file d'attente writeTaskQueue de NioWorker. FailoverClusterInvoker#doInvoke我选择了一个Provider,然后经过各种Consumer Filter,再经过Netty3的pipeline,最后通过NioWorker#scheduleWriteIfNecessary方法,我来到了NioWorker的writeTaskQueue队列中。

当我回头看主线程时,发现他在DefaultFuture中的Condition等待,我不知道他在等什么,也不知道他要等多久。

我在writeTaskQueue队列排了一会队,看到netty3 IO worker线程在永不停歇的执行run方法,大家都称这个为死循环。

最后,我很幸运,NioWorker#processWriteTaskQueue

Quand j'ai regardé le fil de discussion principal, j'ai découvert qu'il attendait dans Condition in DefaultFuture. Je ne savais pas ce qu'il attendait ni combien de temps il devait attendre.

J'ai fait la queue dans la file d'attente writeTaskQueue pendant un moment et j'ai vu que le thread de travail netty3 IO exécutait la méthode d'exécution sans fin. Tout le monde appelait cela une boucle infinie.
5 questions d'entretien Dubbo à haute teneur en or !Enfin, j'ai eu de la chance, NioWorker#processWriteTaskQueue m'a sélectionné, je a été écrit dans le tampon Socket du système d'exploitation. Quoi qu'il en soit, j'ai eu assez de temps pour réfléchir au voyage d'aujourd'hui, j'ai parcouru deux groupes de tournée, appelés le thread principal et netty3 IO. fil de travail. Eh bien, les deux services de groupe de touristes sont tous bons et très efficaces.

J'ai simplement enregistré ce que j'ai vu aujourd'hui et je l'ai dessiné en image. Bien sûr, j'ai ignoré les parties sans importance.

2. Le système d'exploitation envoie un paquet de données
  1. J'ai vécu beaucoup de choses magiques dans le tampon du socket du système d'exploitation.

  2. Dans un endroit appelé couche transport, j'ai ajouté le numéro de port cible et le numéro de port source

  3. Dans un endroit appelé couche réseau, j'ai ajouté l'IP cible et l'IP source, et en même temps temps, via L'IP cible est AND avec le masque pour trouver l'IP du « prochain saut »

    🎜🎜🎜🎜Dans un endroit appelé la couche de liaison de données, j'ai ajouté l'adresse MAC cible du « prochain saut » via la source du protocole ARP. Adresse MAC🎜

Le plus intéressant c'est que nous avons pris un téléphérique section par section. Chaque fois que nous changeions de téléphérique, nous devions modifier l'adresse MAC cible et l'adresse MAC source. Plus tard, j'ai demandé à mes amis du paquet de données dans le. même industrie que ce mode s'appelle "Next Jump", sautez saut après saut. Il y a beaucoup de paquets de données ici. Les plus gros sont dans un seul téléphérique, et les plus petits sont regroupés dans un seul téléphérique. Il y a aussi une chose terrible s'ils sont plus gros, ils doivent être divisés en plusieurs câbles. voitures (bien que cela n'ait pas d'importance pour nos paquets de données). Question), cela s'appelle le déballage et le collage. Pendant cette période, nous avons croisé des commutateurs et des routeurs, et nous étions très heureux de jouer avec ces endroits.

Bien sûr, il y a aussi des choses désagréables, c'est-à-dire des embouteillages, le téléphérique à destination est plein, et il n'y a pas de temps pour être emporté, donc vous ne pouvez qu'attendre.

3. Expérience côté Provider

Finalement, je suis arrivé à destination, je suis monté sur un hors-bord appelé "Zero Copy" et je suis rapidement arrivé à netty4, c'était vraiment magnifique. Après NioEventLoop#processSelectedKeys,再经过pipeline中的各种入站handler,我来到了AllChannelHandler的线程池,当然我有很多选择,但是我随便选了一个目的地,这里会经历解码、一系列的Filter,才会来的目的地“业务方法”,NettyCodecAdapter#InternalDecoderdecoder C'est génial, il peut s'occuper du déballage et du collage.

5 questions d'entretien Dubbo à haute teneur en or !

Je vais rester dans le pool de threads d'AllChannelHandler pendant un moment, j'ai donc également dessiné une image pour enregistrer le voyage.

5 questions d'entretien Dubbo à haute teneur en or !

Depuis, mon voyage est terminé, et de nouvelles histoires se poursuivront avec de nouveaux packages de données.

4. Un nouveau paquet de données a été généré du côté du fournisseur

Je suis un paquet de données, né dans une ville appelée Dubbo2.7.3 Provider, ma mission est de réveiller le fil destiné, ensuite je vous le ferai. commencez un voyage vers un endroit appelé Dubbo2.5.3 Consumer.

Une fois la méthode commerciale du fournisseur exécutée

  • 由业务线程经过io.netty.channel.AbstractChannelHandlerContext#writeAndFlush
  • io.netty.channel.AbstractChannelHandlerContext#writeAndFlush
  • 再经过io.netty.util.concurrent.SingleThreadEventExecutor#execute 执行addTask
  • 将任务放入队列io.netty.util.concurrent.SingleThreadEventExecutor#taskQueue
  • 我便跟随着io.netty.channel.AbstractChannelHandlerContext$WriteTask等待NioEventLoop发车,等待的过程中,我记录了走过的脚步。
  • 5 questions d'entretien Dubbo à haute teneur en or !

    在这里,我看到NioEventLoop是一个死循环,不停地从任务队列取任务,执行任务AbstractChannelHandlerContext.WriteAndFlushTask,然后指引我们到socket缓冲区等候,永不知疲倦,我似乎领略到他身上有一种倔强的、追求极致的匠人精神。

    经过io.netty.channel.AbstractChannel.AbstractUnsafe#write

    再经过io.netty.util. concurrent.SingleThreadEventExecutor#execute 执行addTask🎜🎜将任务放入队列io.netty.util.concurrent.SingleThreadEventExecutor#taskQueue🎜🎜我便跟随着经过io.netty.channel.AbstractChannel.AbstractUnsafe#write,和大多数数据包一样,也是做缆车达到目的地。🎜

    5. Arrivée à Dubbo 2.5.3 Consumer

    Après être arrivé à Dubbo 2.5.3 Consumer, j'ai attendu un moment dans le tampon de socket du système d'exploitation, puis j'ai pris le hors-bord "Zero Copy" et je suis arrivé au destination réelle. La destination dubbo 2.5.3 Consommateur, ici j'ai trouvé, NioWorker#run est une boucle infinie, puis exécute <code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba( 27,31,35,.05);font-family : Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #ff6441;">NioWorker#processSelectedKeys, via NioWorker#read façon de le lire, j'ai atteint le pool de threads de AllChannelHandler, il s'agit d'un pool de threads métier. NioWorker#run是一个死循环,然后执行NioWorker#processSelectedKeys,通过NioWorker#read方式读出来,我就到达了AllChannelHandler的线程池,这是一个业务线程池。

    我在这里等待一会,等任务被调度,我看见com.alibaba.dubbo.remoting.exchange.support.DefaultFuture#doReceived

    J'attendais ici depuis un moment, en attendant que la tâche soit planifiée, et j'ai vu com.alibaba .dubbo.remoting.exchange.support.DefaultFuture#doReceived a été exécuté et le signal de Condition a été exécuté en même temps. J'ai vu un fil bloqué se réveiller au loin. J'ai semblé comprendre qu'à cause de mon arrivée, j'ai réveillé un fil endormi. Je pense que cela devrait être le sens de ma vie.

    À ce stade, ma mission est terminée et ce voyage est terminé.

    Résumé des modèles de thread de netty3 et netty4

    Nous résumons les modèles de thread de netty3 et netty4 sur la base des auto-descriptions des deux paquets de données.

    1. netty4 , pipeline Il est exécuté par le thread IO.

    Résumé : La différence entre les modèles de thread netty3 et netty4 réside dans le processus d'écriture. Dans netty3, le pipeline est exécuté par le thread métier, tandis que dans netty4, indépendamment de la lecture et de l'écriture, le pipeline est exécuté par le thread IO. 5 questions d'entretien Dubbo à haute teneur en or !

    La chaîne de gestionnaires dans ChannelPipeline dans netty4 est uniformément planifiée en série par le thread d'E/S. Qu'il s'agisse d'une opération de lecture ou d'écriture, l'opération d'écriture dans netty3 est traitée par le thread métier. Dans netty4, la consommation de temps causée par le changement de contexte entre les threads peut être réduite, mais dans netty3, les threads métier peuvent exécuter simultanément des chaînes de gestionnaires. Si certaines opérations fastidieuses du gestionnaire entraîneront une faible efficacité de netty4, vous pouvez envisager d'exécuter ces opérations fastidieuses d'abord sur le thread métier au lieu de les traiter dans le gestionnaire. Étant donné que les threads métier peuvent s’exécuter simultanément, l’efficacité peut également être améliorée.

    Dépannage de problèmes difficiles

    J'ai rencontré des problèmes difficiles typiques, par exemple lorsque le didi.log promis par le fournisseur prend le temps normal, mais que le côté consommateur expire actuellement. instructions de dépannage, didi.log Le filtre se situe en fait à un niveau très interne et ne peut souvent pas refléter l'exécution réelle des méthodes commerciales.

    1. Provider En plus de l'exécution de la direction métier, la sérialisation peut également prendre du temps, vous pouvez donc utiliser arthas pour surveiller la méthode la plus externe org.apache.dubbo.remoting.transport.DecodeHandler#received pour exclure les méthodes métier qui sont Question chronophage

    2. L'écriture de paquets de données prend-elle du temps dans le fournisseur ? Surveillez la méthode io.netty.channel.AbstractChannelHandlerContext#invokeWrite

    3. Vous pouvez également vérifier certaines informations du socket TCP actuel. via netstat, telles que Recv-Q , Send-Q et Recv-Q sont des données qui sont arrivées dans le tampon de réception mais qui n'ont pas encore été lues par le code de l'application. Send-Q a atteint le tampon d'envoi, mais l'autre partie n'a pas encore répondu avec les données Ack. Ces deux types de données ne s'accumulent généralement pas. S'ils s'accumulent, il peut y avoir un problème.

    5 questions d'entretien Dubbo à haute teneur en or !
    1. Vérifiez si la méthode Consumer NioWorker#processSelectedKeys (dubbo2.5.3) prend du temps.

    2. Jusqu'aux détails de l'intégralité du lien... le problème peut certainement être résolu.

    Épilogue

    Pendant tout le processus d'interaction, l'auteur omet certains détails des appels de pile de threads et des détails du code source, tels que la sérialisation et la désérialisation, la façon dont Dubbo lit le paquet de données complet, comment sont les filtres triés et distribués avant l'exécution de la méthode métier, et comment le mode Reactor de Netty est-il implémenté ? Ce sont des questions très intéressantes...

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer