web-dev-qa-db-fra.com

Où Elixir / erlang s'intègre-t-il dans l'approche des microservices?

Dernièrement, j'ai fait quelques expériences avec Docker Composer afin de déployer plusieurs microservices de collaboration. Je peux voir les nombreux avantages des microservices, et maintenant qu'il existe un bon ensemble d'outils pour les gérer, je pense qu'il n'est pas extrêmement difficile de sauter dans le wagon des microservices.

Mais, j'ai aussi expérimenté avec Elixir, et j'aime beaucoup les avantages qui en découlent. Étant donné qu'il encourage le conditionnement de votre code dans plusieurs applications découplées et prend en charge les mises à niveau de code à chaud, comment mélangeriez-vous docker avec élixir (ou erlang, d'ailleurs)?

Par exemple, si je veux utiliser Docker car il fournit la parité dev-prod, comment l'élixir s'intègre-t-il? Étant donné que les conteneurs Docker sont immuables, je perds la possibilité de faire des mises à niveau de code à chaud, non? Qu'en est-il des déploiements bleus/verts ou des versions canaries?

Je veux dire, je pourrais simplement écrire des microservices avec Elixir et les utiliser comme s'ils étaient écrits dans une autre langue, le polyglotisme est de toute façon l'un des avantages des microservices, mais je n'obtiens pas tous les avantages de l'utilisation de la plate-forme OTP, je suppose que les applications erlang collaboratives pures sont bien plus optimales que l'utilisation de files d'attente intermédiaires pour communiquer entre des microservices écrits dans des langues différentes (ou non).

103
Papipo

C'est une question très ouverte mais j'essaierai d'illustrer pourquoi Elixir/Erlang peut être la meilleure plate-forme pour développer des systèmes distribués (que vous travailliez avec des microservices).

Tout d'abord, commençons par quelques informations. Erlang VM et sa bibliothèque standard ont été conçus en amont pour la construction de systèmes distribués et cela apparaît vraiment. Pour autant que je sache, c'est le seul runtime et VM = largement utilisé dans la production conçue à l'avance pour ce cas d'utilisation.

Applications

Par exemple, vous avez déjà fait allusion aux "applications". Dans Erlang/Elixir, le code est empaqueté dans des applications qui:

  1. sont démarrés et arrêtés en tant qu'unité. Démarrer et arrêter votre système consiste à démarrer toutes les applications qu'il contient
  2. fournir une structure de répertoire unifiée et une API de configuration (qui n'est pas XML!). Si vous avez déjà travaillé avec et configuré une application OTP, vous savez comment travailler avec n'importe quelle autre
  3. contient votre arbre de supervision d'application, avec tous les processus (par processus, j'entends les "processus VM" qui sont des threads légers de calcul) et leur état

L'impact de cette conception est énorme. Cela signifie que les développeurs d'Elixir, lors de l'écriture d'applications, ont une approche plus explicite pour:

  1. comment leur code est démarré et arrêté
  2. quels sont les processus qui font partie d'une application et donc quel est l'état de l'application
  3. comment ces processus réagiront et seront affectés en cas de crash ou en cas de problème

Non seulement cela, l'outillage autour de cette abstraction est excellent. Si Elixir est installé, ouvrez "iex" et tapez: :observer.start(). En plus d'afficher des informations et des graphiques sur votre système en direct, vous pouvez tuer des processus aléatoires, voir leur utilisation de la mémoire, leur état et plus encore. Voici un exemple d'exécution de cela dans une application Phoenix:

Observer running with a Phoenix application

La différence ici est que les applications et les processus vous donnent une abstraction pour raisonner sur votre code en production . De nombreux langages fournissent des packages, des objets et des modules principalement pour l'organisation du code sans aucune réflexion sur le système d'exécution. Si vous avez un attribut de classe ou un objet singleton: comment raisonner sur les entités qui peuvent le manipuler? Si vous avez une fuite de mémoire ou un goulot d'étranglement, comment pouvez-vous trouver l'entité qui en est responsable?

Si vous demandez à quiconque exécute un système distribué, c'est le genre d'informations qu'il souhaite, et avec Erlang/Elixir, vous avez cela comme élément de base.

La communication

Tout cela n'est vraiment qu'un début. Lors de la construction d'un système distribué, vous devez choisir un protocole de communication et le sérialiseur de données. Beaucoup de gens choisissent HTTP et JSON qui, quand on y pense, est une combinaison très prolixe et coûteuse pour effectuer ce qui est vraiment des appels RPC.

Avec Erlang/Elixir, vous disposez déjà d'un protocole de communication et d'un mécanisme de sérialisation prêts à l'emploi. Si vous voulez que deux machines communiquent entre elles, il vous suffit de leur donner des noms, de vous assurer qu'elles ont le même secret, et vous avez terminé.

Jamie en a parlé à Erlang Factory 2015 et comment ils ont pu en tirer parti pour créer une plateforme de jeu: https://www.youtube.com/watch?v=_i6n-eWiVn4

Si vous souhaitez utiliser HTTP et JSON, c'est très bien aussi et des bibliothèques comme Plug et des frameworks comme Phoenix vous garantiront également que vous êtes productif.

Microservices

Jusqu'à présent, je n'ai pas parlé de microservices. C'est parce que, jusqu'à présent, ils n'ont pas vraiment d'importance. Vous concevez déjà votre système et vos nœuds autour de très petits processus isolés. Appelez-les nanoservices si vous le souhaitez!

Non seulement cela, ils sont également regroupés dans des applications, qui les regroupent en entités qui peuvent être démarrées et arrêtées en tant qu'unité. Si vous avez des applications A, B et C, puis que vous souhaitez les déployer en tant que [A, B] + [C] ou [A] + [B] + [C], vous aurez très peu de mal à le faire car à leur conception inhérente. Ou, mieux encore, si vous voulez éviter d'ajouter la complexité des déploiements de microservices dans votre système à l'avance, vous pouvez simplement les déployer complètement dans le même nœud.

Et, à la fin de la journée, si vous exécutez tout cela en utilisant le protocole distribué Erlang, vous pouvez les exécuter dans différents nœuds et ils pourront en atteindre d'autres tant que vous vous y référerez par {:node@network, :name} au lieu de :name.

Je pourrais aller plus loin mais j'espère vous avoir convaincu à ce stade. :)

130
José Valim