Analyse du processus d'appel inférieur du ruban de composant d'appel de microservice

Processus global d'appel du ruban

Avant d'analyser son principe de mise en œuvre à partir du bas du code source, nous devons d'abord savoir quel type de processus Ribbon est en cours de travail, comme indiqué ci-dessous:

 Je crois que les étudiants qui ont utilisé Ribbon (la couche inférieure de Feign est également le ruban encapsulé) savent que Ribbon est un composant d'appel pour l'équilibrage de charge de découverte de service côté client. Notre fournisseur de services prendra l'initiative de faire rapport au registre nacos (ici nacos Exemple) Pour enregistrer ses propres informations, puis le consommateur de service envoie une demande d'appel au fournisseur de services via le composant RestTemplate annoté avec @LoadBalance. À ce stade, le ruban analysera l'hôte comme l'URL du nom du service et récupérera l'hôte (le nom du service appelé) , Et puis appelez le client nacos pour effectuer la découverte de service en fonction du nom du service dans le serveur nacos, retirez l'ensemble d'instances correspondant au nom du service, puis le ruban utilise son propre algorithme d'équilibrage de charge pour sélectionner l'une des adresses IP d'instance à appeler, c'est à peu près Le flux du ruban lorsqu'il est appelé.

Comment le ruban interfère-t-il avec l'appel du composant RestTemplate?

Dans le RestTemplate, nous pouvons ajouter une série d'intercepteurs pour intercepter notre demande et traiter la logique d'interception associée. En fait, le ruban consiste à ajouter l'intercepteur approprié au RestTemplate, puis à l'ajouter au conteneur. Le travail de cet intercepteur est le processus ci-dessus. Ainsi, lorsque nous utilisons le composant RestTemplate avec l'annotation @LoadBalance, il sera intercepté par l'intercepteur de ruban pour obtenir l'effet d'équilibrage de charge.

Analyse du code source

Ensuite, nous lisons le code source pour voir comment le processus ci-dessus est implémenté dans le code.

1. Quand le ruban Interceptor a-t-il été placé dans le RestTemplate?

Tout d'abord, nous devons trouver l'entrée du code source. Habituellement, ces frameworks et springboot sont intégrés via le mécanisme d'assemblage automatique de springboot. Il est réalisé en ajoutant un ruban Interceptor, donc cet Interceptor devrait être l'entrée. En accédant au package où se trouve l'annotation @LoadBalance, nous pouvons trouver une classe LoadBalanceAutoConfiguration et y trouver une configuration:

 Ce code ajoute un LoadBalancerInterceptor et un RestTemplateCustomizer au conteneur. Ce RestTemplateCustomzier est un personnalisateur RestTemplate. Il ajoute un LoadBalancerInterceptor au RestTemplate ajouté au conteneur, mais quand ce personnalisateur sera-t-il appelé? Nous pouvons voir qu'il existe une autre configuration Bean:

 Ce code ajoute un SmartInitializingSingleton au conteneur. Le personnalisateur est exécuté dans la méthode de cette classe. Tout d'abord, tout le RestTemplate annoté par l'interface @LoadBalanced est obtenu, puis le RestTemplate est parcouru pour exécuter la méthode de notre personnalisateur. Alors, quand la méthode de cette classe est-elle exécutée? Les étudiants qui connaissent Spring doivent savoir que cette classe est une classe d'interface dans Spring. Lorsque tous les Beans terminent leur cycle de vie, découvrez toutes les implémentations de l'interface à partir du conteneur. bean, puis exécutez les méthodes de cette interface.

2. La réalisation de l'équilibrage de charge ruban

Cet intercepteur repose principalement sur le composant LoadBalancerClient pour s'exécuter. Ce composant se trouve dans la classe RibbonAutoConfiguration via la méthode mentionnée au début, et il est exécuté avant que la classe LoadBalancerAutoConfiguration mentionnée ci-dessus ne soit exécutée et ajoutée au conteneur.

 Vous pouvez voir que ce LoadBalancerClient est RibbonLoadBalancerClient, entrez sa méthode d'exécution

 Il y a deux lignes de code ici. Évidemment, commencez par obtenir un équilibreur de charge LoadBalancer, puis utilisez cet équilibreur de charge pour trouver l'adresse IP correspondante d'un service spécifique, puis appelez-le. Le code de getLoadBalancer (serviceId) est en fait Obtenez l'équilibreur de charge correspondant à partir du conteneur Spring, de sorte qu'un équilibreur de charge spécifique doit être ajouté à une classe de configuration @Bean, qui peut être trouvée dans RibbonClientConfiguration en recherchant

 Ensuite, venez à la méthode chooseServer dans getServer. À partir du nom de la méthode, vous pouvez en gros déduire que la méthode est utilisée pour sélectionner un service spécifique. Accédez au chooseServer de la classe parent.

Vous pouvez voir un code clé ici. En déduire grosso modo signifie sélectionner des services spécifiques selon certaines règles, car le ruban fournit plusieurs règles ou règles personnalisées pour sélectionner des services, et cette règle est une interface donc la classe d'implémentation spécifique Il a probablement été ajouté au conteneur via @Bean dans la classe de configuration, et il peut également être trouvé dans RibbonClientConfiguration

Veuillez noter que beaucoup de ces composants sont annotés avec @ConditionalOnMissingBean, nous pouvons donc également ajouter nos propres composants personnalisés si nécessaire.

Mais cette classe n'a pas de méthode choose. En fait, cette méthode est dans sa classe parent PredicateBasedRule

Le code clé est le code dans la case rouge

Obtenez tous les services disponibles et obtenez l'indice de la collection de services via une méthode incrementAndGetModulo. Vous pouvez voir quelles règles la méthode est utilisée pour obtenir

Cas est utilisé ici pour éviter les problèmes de concurrence. En termes simples, il s'agit en fait d'une règle d'interrogation. Jusqu'à présent, le processus de sélection du ruban est terminé.

2. liste des services d'extraction de ruban

Nous avons mentionné ci-dessus que le ruban extrait périodiquement les services du registre pour mettre à jour sa liste de services locaux. Alors, quel est le processus d'extraction? Et comme le ruban doit extraire la liste de services du registre, car le ruban ne spécifie pas quel registre doit y être lié, alors lorsque nous développons un registre par nous-mêmes, le ruban doit fournir l'interface correspondante Intégration avec le registre Jetons un coup d'œil au processus d'intégration du ruban avec le registre pour réaliser le service d'extraction.

Tout d'abord, nous savons que ce processus d'extraction n'est pas déclenché par nous-mêmes, donc la source de l'extraction doit être lorsque la classe est initialisée, elle doit donc être dans la méthode de construction d'une certaine classe, lorsque la classe est ajoutée au conteneur et initialisée Déclenchez après le succès et regardez attentivement. En fait, lorsque l'équilibreur de charge ZoneAwareLoadBalancer est initialisé, sa classe parente DynamicServerListLoadBalancer dispose d'une méthode d'initialisation pour le faire.

Venez à la méthode restOfInit dans la méthode de construction de DynamicServerListLoadBalancer

Ici, nous nous concentrons sur ces deux méthodes dans la boîte rouge, allez dans enableAndInitLearnNewServersFeature

Le serverListUpdate à l'intérieur est en fait ajouté au conteneur via @Bean dans la classe de configuration

Nous entrons donc dans la méthode start de la classe PollingServerListUpdater

Cette méthode est plus critique. On peut voir qu'il existe une nouvelle tâche de thread dans cette méthode, puis le pool de threads est utilisé pour retarder l'exécution de la tâche à une heure fixe. Nous avons déjà dit que le ruban devait extraire régulièrement les services du registre. Étant donné que le délai initial est de 1000 ms, le temps d'exécution de l'intervalle est de 30 s, ce qui signifie que le ruban extrait la dernière liste de services du registre toutes les 30 s par défaut. Et une méthode importante dans cette tâche est doUpdate. Cette méthode consiste à extraire le service du registre. Accédez à la méthode doUpdate.

Vous pouvez voir qu'il existe un code de serverListImpl.getUpdatedListOfServers, ce code consiste à extraire le service de notre registre, découvrez d'abord la classe d'implémentation de serverListImpl

La première classe est chargée à partir de la classe de configuration via @Bean

Ce composant ServerList lit principalement la serverList de l'ensemble dans IClientConfig, et IClientConfig est ajouté au conteneur par @Bean dans la classe de configuration. Par défaut, la serverList de l'ensemble est vide, donc si nous utilisons le ruban seul, nous pouvons @Bean manuellement un ensemble L'IConfig de la liste de serveurs est utilisée, de sorte que le ruban puisse lire la liste de serveurs définie manuellement par elle-même, mais nous l'utilisons généralement dans le registre intégré, donc cette méthode n'a pas de sens

Pour le deuxième composant ServerList, nous pouvons voir un nom spécial NacosServerList . Ce composant est réalisé par nacos en héritant de la classe abstraite exposée par le ruban. La logique à l'intérieur est d'appeler l'API client de nacos pour extraire le service du serveur nacos. Vers le haut

La logique d'appel ici est le code source trouvé par le service dans le client nacos. Parlons-en quand nous examinons le code source de nacos.

Ensuite, chaque fois que le ruban obtient la dernière liste de services du centre d'inscription pour la mettre à jour

 

Venez à la classe parente BaseLoadBalancer de DynamicServerListLoadBalancer, cette classe parente a une variable globale

Cette variable globale est utilisée pour stocker la dernière liste de services extraite du registre

Continuez à regarder sa méthode setServerList, vous pouvez voir le code le plus critique

La référence à la variable de la liste de services de stockage ci-dessus pointe vers notre collection de listes de services nouvellement acquise, qui termine la mise à jour du cache de la liste de services locale

Voici une image pour illustrer le processus de mise en œuvre de l'équilibrage de charge de l'ensemble du service d'extraction par chaque composant du ruban

Je suppose que tu aimes

Origine blog.csdn.net/weixin_37689658/article/details/108732740
conseillé
Classement