Je ne comprends pas le principe du système de suivi distribué. 40 photos vous amènent à vous entraîner

Préface

Dans l'architecture de microservice, une demande implique souvent plusieurs modules, plusieurs middleware et plusieurs machines pour terminer la collaboration. Dans cette série de requêtes d'appel, certaines sont en série et d'autres en parallèle. Alors comment déterminer quelles applications, modules, nœuds et l'ordre d'appel sont appelés derrière cette requête? Comment localiser le problème de performance de chaque module? Cet article révélera la réponse pour vous.

Cet article expliquera à partir des aspects suivants

  • Principe et fonction du système de suivi distribué
  • Principe et conception de l'architecture de SkyWalking
  • Pratique de notre entreprise sur la chaîne d'appels distribués

Principe et fonction du système de suivi distribué

Comment mesurer les performances d'une interface, en général, nous ferons attention au moins aux trois indicateurs suivants

  • Comment connaissez-vous le RT de l'interface?
  • Y a-t-il une réponse anormale?
  • Où est le principal lent?

Architecture monolithique

Dans les premiers temps, lorsque l'entreprise vient de démarrer, elle peut adopter l'architecture monolithique suivante: Pour l'architecture monolithique, quelle méthode devrions-nous utiliser pour calculer les trois indicateurs ci-dessus?

40张图看懂分布式追踪系统原理及实践

 

La chose la plus simple à penser est évidemment d'utiliser AOP

40张图看懂分布式追踪系统原理及实践

 

Utilisez AOP pour imprimer l'heure avant et après l'appel de la logique métier spécifique afin de calculer le temps d'appel global. Utilisez AOP pour intercepter l'exception et savoir également où l'appel a provoqué l'exception.

Architecture de microservices

Dans l'architecture monolithique, tous les services et composants étant sur une seule machine, ces indicateurs de suivi sont relativement faciles à mettre en œuvre. Cependant, avec le développement rapide des affaires, l'architecture monolithique évoluera inévitablement vers une architecture de microservices, comme suit

40张图看懂分布式追踪系统原理及实践

 

Comme le montre l'image: une architecture de microservice légèrement plus complexe

Si certains utilisateurs signalent qu'une page est lente, nous savons que la chaîne d'appel de demande de cette page est A -----> C -----> B -----> D, comment localiser quel module peut être à ce moment Le problème a causé. Chaque service Service A, B, C, D dispose de plusieurs machines. Comment savoir sur quelle machine une demande donnée appelle le service?

40张图看懂分布式追踪系统原理及实践

 

On peut clairement voir qu'en raison de l'incapacité de localiser avec précision le chemin exact que chaque demande passe, il existe les points faibles suivants sous l'architecture de microservice

  1. Difficulté de dépannage et cycle long
  2. Difficile de reproduire des scènes spécifiques
  3. L'analyse des goulots d'étranglement des performances du système est difficile

La chaîne d'appels distribuée est née pour résoudre les problèmes ci-dessus, et ses principales fonctions sont les suivantes

  • Prendre automatiquement des données
  • Analyser les données pour générer une chaîne d'appels complète : avec une chaîne d'appels complète de la demande, le problème a une forte probabilité de récurrence
  • Visualisation des données: la visualisation des performances de chaque composant peut nous aider à localiser le goulot d'étranglement du système et à identifier le problème à temps

Grâce au système de suivi distribué, chaque lien de demande spécifique des demandes suivantes peut être bien localisé, de sorte que le suivi du lien de demande peut être facilement réalisé, et le goulot d'étranglement de performance de chaque module peut être localisé et analysé.

40张图看懂分布式追踪系统原理及实践

 


Standard de chaîne d'appels distribuée - OpenTracing

Connaissant le rôle des chaînes d'appels distribuées, voyons comment implémenter la mise en œuvre et les principes des chaînes d'appels distribuées. Tout d'abord, afin de résoudre le problème d'incompatibilité des API de différents systèmes de traçage distribués, la spécification OpenTracing est née. OpenTracing est un outil léger Niveau de la couche de standardisation, il se situe entre la bibliothèque application / classe et le programme de suivi ou d'analyse des logs.

40张图看懂分布式追踪系统原理及实践

 

De cette manière, OpenTracing fournit des API indépendantes de la plate-forme et du fournisseur afin que les développeurs puissent facilement ajouter la mise en œuvre du système de suivi.

En parlant de cela, avez-vous déjà pensé à une implémentation similaire en Java? N'oubliez pas JDBC, en fournissant un ensemble d'interfaces standard à implémenter par divers fournisseurs, les programmeurs peuvent faire face à la programmation d'interface sans se soucier de l'implémentation spécifique. L'interface ici est en fait une norme, il est donc très important de formuler un ensemble de normes pour activer les composants enfichables.

40张图看懂分布式追踪系统原理及实践

 

Ensuite, nous examinons le modèle de données OpenTracing, il y a principalement les trois suivants

  • Trace : un lien de demande complet
  • Span : Appelez le processus une fois (l'heure de début et l'heure de fin sont requises)
  • SpanContext : trace les informations de contexte global, telles que traceId

Il est très important de comprendre ces trois concepts. Afin de permettre à chacun de mieux comprendre ces trois concepts, j'ai spécialement dessiné une image

40张图看懂分布式追踪系统原理及实践

 

Comme le montre la figure, la requête complète d'une commande est une trace complète . Evidemment, pour cette requête, il doit y avoir un identifiant global pour identifier cette requête. Chaque appel est appelé un Span, et chaque appel doit être amené. Le TraceId global, pour que le TraceId global puisse être associé à chaque appel. Ce TraceId est transmis via le SpanContext. Puisqu'il est nécessaire de transmettre, il doit évidemment être appelé conformément au protocole. Comme le montre la figure, nous comparons le protocole de transmission à une voiture, SpanContext aux marchandises et Span aux routes.

Après avoir compris ces trois concepts, permettez-moi de voir comment le système de suivi distribué collecte la chaîne d'appels du microservice dans le graphique unifié.

40张图看懂分布式追踪系统原理及实践

 

Nous pouvons voir qu'il y a un collecteur dans la couche inférieure qui a collecté des données dans l'obscurité, donc quelles informations seront collectées chaque fois que Collector est appelé.

  1. Global trace_id: Ceci est évident, afin que chaque sous-appel puisse être associé à la requête d'origine
  2. span_id: 0, 1, 1.1, 2 dans la figure, afin que vous puissiez identifier quel appel
  3. parent_span_id: Par exemple, le span_id de b appelant d est 1.1, alors son parent_span_id est le span_id d'un appel b, qui vaut 1, de sorte que les deux appels adjacents peuvent être associés.

Avec ces informations, les informations collectées par Collector pour chaque appel sont les suivantes

40张图看懂分布式追踪系统原理及实践

 

Selon ces informations graphiques, il est évident que la vue visuelle de la chaîne d'appels peut être dessinée comme suit

40张图看懂分布式追踪系统原理及实践

 

Ainsi, un système de suivi distribué complet est réalisé.

L'implémentation ci-dessus semble vraiment simple, mais il y a plusieurs problèmes qui nous obligent à réfléchir attentivement

  1. Comment collecter automatiquement les données span: collecte automatique, pas d'invasion du code métier
  2. Comment transférer le contexte entre les processus
  3. Comment garantir l'unicité globale de traceId
  4. Un si grand nombre de demandes affectera-t-il les performances?

Ensuite, laissez-moi voir comment SkyWalking résout les quatre problèmes ci-dessus

Principe et conception de l'architecture de SkyWalking

Comment collecter automatiquement les données span

SkyWalking adopte la  forme de plug-in  +  javaagent pour réaliser la collecte automatique des données span, afin qu'il puisse être non-invasif pour le code  , plug-in signifie plug-in, bonne extensibilité (ce qui suit va vous expliquer comment définir votre propre plug-in )

40张图看懂分布式追踪系统原理及实践

 


Comment transférer le contexte entre les processus

Nous savons que les données sont généralement divisées en en-tête et en corps, tout comme http a un en-tête et un corps, RocketMQ a également MessageHeader, Message Body, le corps contient généralement des données commerciales, il n'est donc pas approprié de passer le contexte dans le corps, mais devrait passer le contexte dans l'en-tête, comme indiqué sur la figure

40张图看懂分布式追踪系统原理及实践

 

La pièce jointe dans dubbo est équivalente à l'en-tête, nous mettons donc le contexte dans la pièce jointe, ce qui résout le problème de transfert de contexte.

40张图看懂分布式追踪系统原理及实践

 

Astuces: Le processus de transfert de contexte ici est géré dans le plugin dubbo, et l'entreprise n'est pas au courant. Comment ce plugin est implémenté, je vais l'analyser ci-dessous

Comment garantir l'unicité globale de traceId

Pour garantir l'unicité globale, nous pouvons utiliser des identifiants distribués ou générés localement. Si vous utilisez des identifiants distribués, vous devez avoir un expéditeur. Chaque fois que vous demandez, vous devez d'abord demander l'expéditeur. Il y aura une surcharge d'appel réseau, donc SkyWalking finira par Il utilise la méthode de génération d'ID localement, il utilise le célèbre algorithme de snowflow et a des performances élevées.

40张图看懂分布式追踪系统原理及实践

 


Illustration: id généré par l'algorithme de flocon de neige

Cependant, l'algorithme de flocon de neige a un problème bien connu: le rappel temporel , qui peut entraîner la génération d'identifiants en double. Alors, comment SkyWalking résout-il le problème du rappel temporel?

40张图看懂分布式追踪系统原理及实践

 

Chaque fois qu'un identifiant est généré, l'heure à laquelle l'identifiant a été généré (lastTimestamp) est enregistrée. Si l'heure actuelle est inférieure à l'heure à laquelle l'identifiant a été généré pour la dernière fois (lastTimestamp), cela signifie qu'un rappel de l'heure s'est produit et un nombre aléatoire sera généré comme traceId. Il peut y avoir des étudiants qui veulent être plus réels ici, et ils peuvent penser que le nombre aléatoire généré sera également le même que l'ID global généré. Ce serait mieux si vous ajoutez une autre couche de vérification.

Ici, je veux parler du choix de la conception du système.Tout d'abord, si l'unicité du nombre aléatoire généré est vérifiée, il y aura sans aucun doute une couche supplémentaire d'appel, il y aura une certaine perte de performance, mais en fait, la probabilité de rappel temporel est très faible. (Après l'événement, l'entreprise sera grandement affectée en raison du désordre du temps machine, donc l'ajustement du temps machine doit être prudent), plus la probabilité que les nombres aléatoires générés se chevauchent est également très faible, et il n'est vraiment pas nécessaire d'en ajouter un ici. Vérification de l'unicité globale de la couche. Pour la sélection des solutions techniques, il faut éviter la sur-conception.

Avec autant de demandes, toute collecte affectera-t-elle les performances?

Si vous appelez pour chaque demande à collecter, il ne fait aucun doute que la quantité de données sera très importante, mais à son tour, demandez-vous s'il est vraiment nécessaire de collecter pour chaque demande. En fait, ce n'est pas nécessaire. Nous pouvons définir la fréquence d'échantillonnage et échantillonner uniquement Pour une partie des données, SkyWalking par défaut échantillonne 3 fois en 3 secondes, et les autres demandes ne sont pas échantillonnées, comme indiqué sur la figure

40张图看懂分布式追踪系统原理及实践

 

Ce type de fréquence d'échantillonnage est en fait suffisant pour nous permettre d'analyser les performances du composant Quels problèmes y aura-t-il lors de l'échantillonnage de données à une fréquence de 3 fois en 3 secondes? Dans l'idéal, chaque appel de service se fait au même moment (comme illustré dans la figure ci-dessous). Il est donc normal d'échantillonner au même moment à chaque fois.

40张图看懂分布式追踪系统原理及实践

 

Cependant, en production, il est fondamentalement impossible que chaque appel de service soit appelé au même moment, car il y a des retards d'appels réseau pendant la période, et la situation d'appel réelle est susceptible d'être comme la figure suivante

40张图看懂分布式追踪系统原理及实践

 

Dans ce cas, certains appels seront échantillonnés sur le service A, mais pas sur les services B et C, et il est impossible d'analyser les performances de la chaîne d'appels. Alors, comment SkyWalking le résout-il?

Il est résolu comme ceci: si l'amont porte le contexte (indiquant un échantillonnage en amont), l'aval est obligé de collecter des données. Cela peut garantir l'intégrité du lien.

Infrastructure de SkyWalking

La structure de base de SkyWalking est la suivante. On peut dire que presque tous les appels distribués sont composés des composants suivants

40张图看懂分布式追踪系统原理及实践

 

首先当然是节点数据的定时采样,采样后将数据定时上报,将其存储到 ES, MySQL 等持久化层,有了数据自然而然可根据数据做可视化分析。


SkyWalking 的性能如何

接下来大家肯定比较关心 SkyWalking 的性能,那我们来看下官方的测评数据

40张图看懂分布式追踪系统原理及实践

 

图中蓝色代表未使用 SkyWalking 的表现,橙色代表使用了 SkyWalking 的表现,以上是在 TPS 为 5000 的情况下测出的数据,可以看出,不论是 CPU,内存,还是响应时间,使用 SkyWalking 带来的性能损耗几乎可以忽略不计。

接下来我们再来看 SkyWalking 与另一款业界比较知名的分布式追踪工具 Zipkin, Pinpoint 的对比(在采样率为 1 秒 1 个,线程数 500,请求总数为 5000 的情况下做的对比),可以看到在关键的响应时间上, Zipkin(117ms),PinPoint(201ms)远逊色于 SkyWalking(22ms)!

40张图看懂分布式追踪系统原理及实践

 

从性能损耗这个指标上看,SkyWalking 完胜!

再看下另一个指标:对代码的侵入性如何,ZipKin 是需要在应用程序中埋点的,对代码的侵入强,而 SkyWalking 采用 javaagent + 插件化这种修改字节码的方式可以做到对代码无任何侵入,除了性能和对代码的侵入性上 SkyWaking 表现不错外,它还有以下优势几个优势

  • 对多语言的支持,组件丰富:目前其支持 Java, .Net Core, PHP, NodeJS, Golang, LUA 语言,组件上也支持dubbo, mysql 等常见组件,大部分能满足我们的需求。
  • 扩展性:对于不满足的插件,我们按照 SkyWalking 的规则手动写一个即可,新实现的插件对代码无入侵。

我司在分布式调用链上的实践

SkyWalking 在我司的应用架构

De ce qui précède, nous pouvons voir que SkyWalking a de nombreux avantages, alors avons-nous utilisé tous ses composants? En fait, ce n'est pas le cas. Jetons un coup d'œil à l'architecture de ses applications dans notre entreprise.

40张图看懂分布式追踪系统原理及实践

 

On peut voir sur la figure que nous n'utilisons que l'agent de SkyWalking pour l'échantillonnage, et abandonnons les trois autres composants «rapport et analyse de données», «stockage de données» et «visualisation de données», alors pourquoi ne pas utiliser directement l'ensemble de SkyWalking La solution est que notre écosystème de surveillance Marvin était relativement complet avant de nous connecter à SkyWalking. Si nous le remplaçons par SkyWalking, ce n'est pas nécessaire. Marvin peut répondre à nos besoins dans la plupart des scénarios. Le coût du remplacement du système est élevé, et troisièmement, il est très coûteux de reconnecter les utilisateurs pour apprendre.

Cela nous donne également une idée: il est très important pour tout produit de saisir l’opportunité, et le coût de remplacement des produits suivants sera élevé. Saisir la première opportunité signifie saisir l’esprit de l’utilisateur. C'est comme WeChat. Bien que l’interface utilisateur soit bien conçue, elle est Whatsapp ne peut pas être fait dans les pays étrangers, car la première opportunité est partie.

En revanche, pour l'architecture, il n'y a pas de meilleur, seulement le plus approprié. Combiner le scénario commercial actuel pour équilibrer le compromis est l'essence même de la conception de l'architecture

Quelles transformations et pratiques notre entreprise a apportées à SkyWalking

Notre entreprise a principalement effectué les transformations et pratiques suivantes

  1. L'environnement de pré-version nécessite un échantillonnage obligatoire en raison du débogage
  2. Obtenir un échantillonnage plus fin?
  3. TraceId intégré dans le journal
  4. Implémentation auto-développée du plug-in SkyWalking

L'environnement de pré-version nécessite un échantillonnage obligatoire en raison du débogage

D'après l'analyse ci-dessus, nous pouvons voir que Collector échantillonne régulièrement en arrière-plan. N'est-ce pas bien? Pourquoi devons-nous implémenter un échantillonnage forcé? Il reste à dépanner les problèmes de positionnement. Parfois il y a des problèmes en ligne. Nous espérons le reproduire en pré-version, dans l'espoir de voir la chaîne d'appels complète de cette requête, il est donc nécessaire d'implémenter l'échantillonnage forcé en pré-version. Nous avons donc modifié le plug-in dubbo de Skywalking pour implémenter l'échantillonnage forcé

Nous apportons une  paire clé-valeur comme force_flag = true sur le cookie demandé  pour indiquer que nous voulons forcer l'échantillonnage. Une fois que la passerelle reçoit ce cookie, elle apportera la paire clé-valeur force_flag = true dans la pièce jointe dubbo, puis Le plug-in dubbo de skywalking peut juger s'il s'agit d'un échantillonnage forcé basé sur cela. S'il y a cette valeur, cela signifie un échantillonnage forcé. S'il n'y a pas une telle valeur, il prendra un échantillonnage de synchronisation normal.

40张图看懂分布式追踪系统原理及实践

 

Obtenir un échantillonnage plus fin?

Hah a appelé un échantillonnage plus fin. Examinez d'abord la méthode d'échantillonnage par défaut du skywalking, à savoir l'échantillonnage unifié

40张图看懂分布式追踪系统原理及实践

 

Nous savons que cette méthode utilise par défaut 3 fois avant l'échantillonnage en 3 secondes, et toutes les autres requêtes sont rejetées. Dans ce cas, il y a un problème. Supposons qu'il y ait plusieurs appels dubbo, mysql, redis dans les 3 secondes sur cette machine, mais si les trois premières fois S'ils sont tous des appels dubbo, d'autres appels comme mysql, redis, etc. ne peuvent pas être échantillonnés, nous avons donc modifié le skywalking pour obtenir un échantillonnage de groupe, comme suit

40张图看懂分布式追踪系统原理及实践

 

En d'autres termes, 3 échantillons de redis, dubbo, mysql, etc. sont réalisés en 3 secondes, ce qui évite ce problème

Comment intégrer traceId dans le journal?

Le traceId intégré dans le journal de sortie est pratique pour résoudre les problèmes, il est donc très nécessaire de taper le traceId Comment intégrer le traceId dans le journal? Nous utilisons log4j. Ici, nous devons comprendre le mécanisme du plug-in log4j. Log4j nous permet de personnaliser le plug-in pour générer le format du journal. Tout d'abord, nous devons définir le format du journal et intégrer% traceId dans le format de journal personnalisé en tant que compte Espace réservé, comme suit

40张图看懂分布式追踪系统原理及实践

 

Ensuite, nous implémentons un plug-in log4j, comme suit

40张图看懂分布式追踪系统原理及实践

 

Tout d'abord, le plug-in log4j doit définir une classe qui hérite de la classe LogEventPatternConverter et se déclare comme un plug-in avec le plug-in standard. L'espace réservé à remplacer est spécifié via l'annotation @ConverterKeys, puis remplacé dans la méthode format Laissez tomber. De cette façon, le TraceId que nous voulons apparaîtra dans le journal, comme suit

40张图看懂分布式追踪系统原理及实践

 

Quels plugins Skywalking ont été développés par notre société

SkyWalking a implémenté de nombreux plug-ins, mais ne fournit pas de plug-ins Memcached et Druid, nous avons donc auto-développé ces deux plug-ins selon ses spécifications.

40张图看懂分布式追踪系统原理及实践

 

Comment implémenter le plug-in, vous pouvez voir qu'il est principalement composé de trois parties

  1. Classe de définition du plug-in: spécifiez la classe de définition du plug-in. Enfin, le plug-in sera empaqueté et généré en fonction de la classe de définition ici
  2. Instrumentation: spécifiez l'aspect, le point de contact, quelle méthode de quelle classe doit être améliorée
  3. Intercepteur, spécifiez l'étape 2 Il est important d'écrire une logique améliorée à l'avant de la méthode, à l'arrière ou dans l'exception

Peut-être que vous ne le comprenez toujours pas après l'avoir lu. Expliquons-le brièvement avec le plug-in dubbo. Nous savons que dans le service dubbo, chaque requête reçoit un message de netty et le soumet au pool de threads métier pour traitement, jusqu'à l'appel réel à la fin de la méthode métier. Après plus d'une douzaine de traitement de filtre au milieu

40张图看懂分布式追踪系统原理及实践

 

Et MonitorFilter peut intercepter toutes les requêtes client ou les requêtes de traitement du serveur, afin que nous puissions améliorer MonitorFilter, avant d'appeler la méthode invoke, injecter le traceId global dans la pièce jointe de son Invocation, afin de garantir que la requête arrive au réel Le traceId global existe déjà avant la logique métier.

Nous devons donc évidemment spécifier la classe que nous voulons améliorer (MonitorFilter) dans le plug-in, et améliorer sa méthode (invoke). Quelles améliorations faut-il apporter à cette méthode? C'est ce que fait l'intercepteur (Inteceptor), jetons un coup d'œil Instrumentation dans le plug-in Dubbo (DubboInstrumentation)

40张图看懂分布式追踪系统原理及实践

 

Jetons un coup d'œil à ce que fait l'Inteceptor décrit dans le code. Les étapes clés sont répertoriées ci-dessous

40张图看懂分布式追踪系统原理及实践

 

Tout d'abord, beforeMethod représente que la méthode sera appelée avant que la méthode invoke de MonitorFilter ne soit exécutée, et le correspondant est afterMethod, qui représente la logique d'amélioration après l'exécution de la méthode invoke.

其次我们从第 2,3点可以看到,不管是 consumer 还是 provider, 都对其全局 ID 作了相应处理,这样确保到达真正的业务层的时候保证有了此全局 traceid,定义好 Instrumentation 和 Interceptor 后,最后一步就是在 skywalking.def 里指定定义的类

// skywalking-plugin.def 文件
dubbo=org.apache.skywalking.apm.plugin.asf.dubbo.DubboInstrumentation

这样打包出来的插件就会对 MonitorFilter 的 invoke 方法进行增强,在 invoke 方法执行前对期 attachment 作注入全局 traceId 等操作,这一切都是静默的,对代码无侵入的。

总结

本文由浅入深地介绍了分布式追踪系统的原理,相信大家对其作用及工作机制有了比较深的理解,特别需要注意的是,引入某项技巧,一定要结合现有的技术架构作出最合理的选择,就像 SkyWalking 有四个模块,我司只采用其 agent 采样功能一样,没有最好的技术,只有最合适的技术,通过此文,相信大家应该对 SkyWalking 的实现机制有了比较清晰的认识,文中只是介绍了一下 SkyWalking 的插件实现方式,不过其毕竟是工业级软件,要了解其博大精深,还要多读源码哦。

更多面试学习资料已经整理到我的git仓库中,有需要的朋友自取:https://gitee.com/biwangsheng/personal.git

 

Je suppose que tu aimes

Origine blog.csdn.net/weixin_42864905/article/details/108512683
conseillé
Classement