Principales fonctionnalités qu’Apache Kafka fournit sur les files d’attente de messages
Apache Kafka, ci-après considéré comme étant simplement Kafka pour plus de commodité (à ne pas confondre avec celui qui a réellement inspiré le nom de la technologie), à l’origine une plate-forme de streaming distribuée au sein de LinkedIn et plus tard open source dans le monde, est maintenant l’épine dorsale de chaque entreprise cela donne un sens aux énormes volumes de données qu’ils acquièrent à la fois auprès des utilisateurs et génèrent dans le cadre de leurs activités normales dans le monde connecté.
Pourquoi envoyer des messages à travers les systèmes?
Au fur et à mesure que les systèmes grandissent et évoluent, ils se divisent en un plus grand nombre de composants disparates, à la fois pour améliorer la résilience de l’ensemble du système (donc l’erreur dans un composant n’entraîne pas le système entier vers le bas) ainsi que pour gérer l’augmentation de la charge dans les performances les attentes du système (un ensemble fixe de machines ne peut effectuer qu’un certain nombre d’opérations dans une fenêtre de temps donnée, de sorte qu’elles finissent par évoluer pour répondre à la charge croissante). Le système d’origine est ainsi décomposé en sous-systèmes plus petits (certains le poussent à l’extrême avec des microservices et des nanoservices) et dans d’autres cas, il s’agissait de systèmes disparates au départ (systèmes opérationnels et analytiques). Cependant, il ne suffit pas de décomposer la logique de traitement en composants séparés et de les déployer indépendamment. Chacun de ces sous-systèmes doit également avoir accès aux données pour effectuer le traitement prévu. D’où la nécessité d’échanger des informations entre tous ces sous-systèmes qui composent l’ensemble du système. C’est ainsi que les systèmes de messagerie ont vu le jour. (Les systèmes opérationnels et analytiques étaient toujours séparés et disposaient d’un ensemble distinct de technologies pour construire des ETL. Mais Kafka a unifié ces systèmes en un tout plus grand afin qu’il puisse servir à la fois les systèmes opérationnels et analytiques en utilisant une seule infrastructure.)
Nous comprenons maintenant pourquoi des systèmes de messagerie sont nécessaires. Les middleware orientés messages, tels qu’ils sont parfois appelés, sont basés sur des protocoles tels que ceux destinés à envoyer et recevoir des messages sur des systèmes hétérogènes dans l’environnement de systèmes distribués. Ces interactions via des messages éliminent le besoin de temps de compilation et de dépendances d’exécution sur d’autres systèmes. Cela permet une évolution indépendante des systèmes, tous faiblement couplés, à l’exception de l’infrastructure de messagerie qui les maintient ensemble.
Très bien jusqu’à présent. Quels sont donc les inconvénients? Pour comprendre que nous devons approfondir un peu plus l’architecture des systèmes de messagerie.
Toutes les files d’attente de messages dépendent de courtiers déployés dans un cluster pour gérer les messages qui arrivent et quittent le système. Les éditeurs publient des messages dans les files d’attente et les abonnés s’abonnent aux messages de ces files d’attente. Ce sont les clients du système de messagerie. Les files d’attente de messages elles-mêmes sont gérées par des courtiers et les courtiers acheminent les messages selon les besoins et gardent une trace de la distance parcourue par chaque abonné dans une file d’attente.
Si l’éditeur génère des messages dans la file d’attente très rapidement et que l’abonné lit les messages très lentement, les courtiers doivent garder les messages pour l’abonné disponibles aussi longtemps qu’il lui faudra pour terminer la lecture et le traitement des messages dans le queue. Imaginez maintenant que des centaines de files d’attente se remplissent chacune de messages à consommer par leurs abonnés respectifs. Comme vous pouvez le voir, cela entraînera des goulots d’étranglement sur les courtiers. Les courtiers étant le cluster centralisé qui gère tous les messages, les performances des clients (éditeurs et abonnés) et le débit des messages affectent les performances de l’ensemble du système de messagerie. Il s’agit d’un inconvénient pour faire évoluer les systèmes de messagerie en tant que bus d’entreprise pour l’ensemble de l’organisation.
En examinant l’architecture, nous avons appris comment les systèmes de messagerie fournissent des files d’attente aux éditeurs et aux abonnés pour interagir les uns avec les autres. Imaginez maintenant ce scénario où nous avons une boutique de commerce électronique et où plusieurs services interagissent avec le service de commande pour suivre ce qui se passe. Le service des commandes gère les commandes, mais le service d’inventaire doit connaître les articles et les quantités fabriqués dans chaque commande afin que le niveau de stock soit mis à jour. Il existe également un service de notification qui envoie des notifications au client et à certains fournisseurs sur les articles commandés. Ensuite, il y a le service d’expédition qui doit connaître l’adresse de livraison. Nous avons donc un scénario où plusieurs systèmes sont impliqués dans l’exécution d’une commande. Chacune de ces interactions peut être effectuée de manière asynchrone afin que l’utilisateur n’attende pas pendant le traitement de la commande et que tous les systèmes ci-dessus soient informés des informations requises de la commande. Dans le monde du traitement des messages, chacune de ces interactions nécessite une file d’attente. C’est-à-dire qu’une file d’attente pour Inventory Service, une autre file d’attente pour Notification Service, une autre file d’attente pour Shipping Service et Order Service doivent publier le même message dans toutes ces files d’attente concernant la commande qui a été passée. Et ici, nous pensions avoir une architecture bien découplée où chaque système interagissait les uns avec les autres via des messages!
Ce problème peut être résolu en créant des sujets virtuels et en ajoutant plusieurs abonnés au même sujet mais une file d’attente distincte pour chaque abonné afin de s’assurer que tous reçoivent une copie du même message. Order Service n’a alors pas à envoyer le même message à plusieurs files d’attente, mais à un seul sujet. Cependant, l’infrastructure du courtier est devenue encore plus complexe, devant gérer non seulement les messages et les files d’attente, mais également les rubriques et les abonnés à chaque rubrique et les files d’attente spécifiques à leur affecter. L’intégration au bon sujet et à la file d’attente pour un abonné représente un effort supplémentaire pour chaque nouvel abonné du système de messagerie.
À mon avis, les raisons ci-dessus sont la plus grande victoire pour Kafka par rapport aux systèmes de messagerie typiques.
Laisse-moi expliquer. Encore une fois, ce n’est pas parce que Kafka est la solution miracle ou même que les files d’attente de messages sont intrinsèquement mauvaises. Chacun résout un ensemble spécifique de problèmes et les files d’attente de messages ne sont parfois pas la meilleure solution pour envoyer les mêmes données sur plusieurs systèmes. Nous allons commencer par regarder l’architecture.
À un niveau élevé, Kafka écrit les événements dans un journal immuable, partitionné par sujet. Les producteurs d’événements continuent d’écrire sur le sujet et les consommateurs d’événements continuent de lire sur le sujet. La longévité des événements est configurée par sujet. Les événements publiés sur un seul sujet sont écrits dans les partitions du sujet (dont le nombre est configuré lors de la création du sujet, un plus grand nombre de partitions pour un débit plus élevé) par les courtiers. Tous les consommateurs lisent à partir de toutes les partitions d’un sujet (parallélisme limité par le nombre de partitions) et chacun valide ses propres décalages pour suivre dans quelle mesure ils ont consommé le sujet. Les décalages sont comparables aux numéros de ligne des fichiers, une partition est constituée de plusieurs segments, chacun contenant des fichiers.
Par conséquent, il incombe désormais à chaque consommateur de suivre dans quelle mesure il a lu sur chaque sujet. En même temps, cette architecture simplifie grandement les courtiers et se traduit par une meilleure évolutivité des courtiers au service des clients.
Examinons maintenant les inconvénients des files d’attente de messages décrits précédemment dans le contexte de Kafka.
Comme décrit dans la section architecture, les courtiers gèrent les sujets qui contiennent une seule copie du message (ou comme nous l’appelons «événement»), autre que la réplication effectuée pour la durabilité des événements. Tous les consommateurs lisent les mêmes événements lorsqu’ils consomment le sujet, ils lisent les événements dans l’ordre dans lequel ils sont écrits dans le sujet et gèrent leur propre suivi de décalage. Comme vous pouvez le voir, les courtiers sont plus simples et la longévité d’un événement (message) est configurée comme une période de temps fixe, plutôt que lorsque tous les consommateurs ont consommé le message, éliminant ainsi la nécessité de suivre cet état. L’architecture résultante élimine beaucoup de frais généraux sur les courtiers et les performances du cluster de courtiers ne sont plus fonction du nombre d’éditeurs et d’abonnés. Par conséquent, les consommateurs peuvent désormais lire les événements des sujets à leur propre rythme, peuvent effectuer un traitement plus lourd tout en consommant chaque événement; il n’y a aucune pression pour supprimer les messages de la file d’attente aussi rapidement que possible.
Dans le système de traitement des événements basé sur Kafka, chaque consommateur peut recevoir tous les événements publiés sur le sujet, aucune file d’attente par consommateur et donc aucune configuration et aucun routage requis par consommateur. Cette architecture supprime donc tout couplage entre le producteur et le consommateur d’événements.
Contrairement à Message Queues où un message est à certains égards une commande ou une instruction avec des données pour effectuer une opération spécifique ciblant un système spécifique qui consomme le message, les événements publiés sur Kafka sont des changements d’état qui sont survenus à l’éditeur de l’événement diffusé à tous. les parties intéressées par ce changement d’état. Il appartient ensuite au consommateur de décider quelle action doit être effectuée. Il existe simplement un contrat entre le producteur et le consommateur dans le schéma événementiel, qui peut également évoluer de manière indépendante. (L’écosystème Kafka permet de gérer cette évolution du schéma.)
En résumé, les producteurs et les consommateurs peuvent exister indépendamment l’un de l’autre. Les nouveaux consommateurs peuvent rejoindre le système en commençant simplement à consommer un sujet. De même, les consommateurs existants peuvent repartir sans que des changements soient nécessaires sur les courtiers pour l’intégration ou la désactivation.
Dans cet article, j’ai évoqué deux raisons principales d’utiliser Kafka dans une entreprise. L’utilisation de Kafka est un bon moyen d’éliminer l’inadéquation d’impédance entre les producteurs et les consommateurs. Chacun peut procéder à son propre rythme sans impact sur d’autres parties de l’écosystème, ce qui en fait un logiciel d’infrastructure d’entreprise robuste. Les interactions via Kafka ne sont pas point à point permettant un véritable découplage des systèmes.
Kafka n’est pas sans inconvénients. Les implémentations de Message Queue sont plus simples pour les clients par rapport à Kafka où ils doivent suivre leur propre état. La communication n’est pas point à point. Par conséquent, les files d’attente de lettres mortes et les modèles de conception de messagerie similaires ne s’appliquent pas directement. En fait, il est préférable de considérer les flux d’événements sur Kafka comme une diffusion à sens unique en supposant qu’aucune interaction future avec le producteur des événements dans le contexte d’un sujet spécifique.
Les capacités de routage des courtiers de messages permettent également de filtrer les messages via des sélecteurs si un consommateur spécifique n’est pas intéressé par un sous-ensemble de messages. Les courtiers Kafka n’offrent pas un tel filtrage. La conception des sujets doit donc être beaucoup plus granulaire, afin que les consommateurs puissent éviter de consommer certains sujets au total.
Kafka est livré avec une architecture simplifiée qui permet l’évolutivité. L’ajout de nouveaux producteurs et consommateurs n’aura pas d’impact significatif sur les performances. Les performances et l’évolutivité de Kafka deviennent donc fonction du volume de données qu’il gère et non du nombre de clients qu’il dessert. Ces fonctionnalités contribuent à son rôle de plateforme de streaming d’événements à l’échelle de l’entreprise.