Claustro → xestión sinxela de cluster OTP

Case todas as aplicacións empresariais exitosas entran tarde ou cedo nunha fase na que se require escala horizontal. En moitos casos, pode simplemente iniciar unha nova instancia e reducir a media de carga. Pero tamén hai casos menos triviais nos que debemos asegurarnos de que os distintos nodos se coñezan e distribuír coidadosamente a carga de traballo.

Claustro → xestión sinxela de cluster OTP

Resultou tan afortunado que Erlang, que escollemos pola súa agradable sintaxe e o bombo ao seu redor, ten un primeiro nivel soporte para sistemas distribuídos. En teoría, isto soa completamente trivial:

O paso de mensaxes entre procesos en diferentes nodos, así como entre ligazóns e monitores, é transparente […]

Na práctica, todo é un pouco máis complicado. Distribuído Erlang foi desenvolvido cando "contedor" significaba unha gran caixa de ferro para o envío, e "docker" era simplemente un sinónimo de estibador. EN IP4 había moitos enderezos desocupados, as interrupcións da rede eran normalmente causadas por ratos que masticaban o cable e o tempo medio de funcionamento do sistema de produción mediuse en décadas.

Agora todos somos incriblemente autosuficientes, empaquetados e distribuídos Erlang nun entorno onde os enderezos IP dinámicos se reparten co principio de gran aleatoriedade, e os nodos poden aparecer e desaparecer ao capricho do talón esquerdo do planificador. Para evitar pilas de código estándar en todos os proxectos que executan un programa distribuído Erlang, para combater o ambiente hostil, é necesaria axuda.

Nota: Son consciente de que hai libcluster. É moi chulo, ten máis de mil estrelas, o autor é famoso na comunidade, e todo iso. Se os métodos que ofrece este paquete para crear e manter un clúster son suficientes para ti, estou feliz por ti. Por desgraza, necesito moito máis. Quero controlar a configuración en detalle e non ser un espectador externo no teatro da reorganización do clúster.

Requisitos

O que necesitaba persoalmente era unha biblioteca que se fixera cargo da xestión do clúster e tivese as seguintes propiedades:

  • traballo transparente tanto cunha lista codificada de nós como con descubrimento dinámico a través dos servizos Erlang;
  • devolución de chamada totalmente funcional para cada cambio de topoloxía (nodo alí, nodo aquí, inestabilidade da rede, divisións);
  • interface transparente para lanzar un clúster con nomes longos e curtos, como con :nonode@nohost;
  • Soporte de Docker listo para usar, sen ter que escribir código de infraestrutura.

Isto último significa que despois de probar a aplicación localmente en :nonode@nohost, ou nun ambiente distribuído artificialmente usando test_cluster_task, só quero correr docker-compose up --scale my_app=3 e vexa como executa tres instancias en docker sen ningún cambio de código. Tamén quero aplicacións dependentes como mnesia - cando a topoloxía cambia, entre bastidores reconstrúen o clúster en directo sen ningunha patada adicional da aplicación.

Claustro non pretendía ser unha biblioteca capaz de todo, desde soportar un clúster ata facer café. Non é unha bala de prata que pretende cubrir todos os casos posibles, nin ser unha solución académicamente completa no sentido de que os teóricos de CS poñer neste termo. Esta biblioteca está deseñada para cumprir un propósito moi claro, pero fai o seu traballo non demasiado grande á perfección. Este obxectivo será proporcionar unha transparencia total entre o entorno de desenvolvemento local e un entorno elástico distribuído e cheo de contedores hostís.

Enfoque escollido

Claustro está pensado para ser executado como unha aplicación, aínda que os usuarios avanzados poden traballar coa montaxe e o mantemento do clúster manualmente executando directamente Cloister.Manager na árbore de supervisor da aplicación de destino.

Cando se executa como unha aplicación, a biblioteca confía config, do que se le os seguintes valores básicos:

config :cloister,
  otp_app: :my_app,
  sentry: :"cloister.local", # or ~w|n1@foo n2@bar|a
  consensus: 3,              # number of nodes to consider
                             #    the cluster is up
  listener: MyApp.Listener   # listener to be called when
                             #    the ring has changed

Os parámetros anteriores significan literalmente o seguinte: Claustro usado para aplicación OTP :my_app, usos descubrimento do servizo erlang para conectar nodos, polo menos tres, e MyApp.Listener módulo (implementación @behaviour Cloister.Listener) está configurado para recibir notificacións sobre cambios de topoloxía. Pódese atopar unha descrición detallada da configuración completa en documentación.

Con esta configuración, a aplicación Claustro vontade lanzamento por etapas, atrasando o proceso de inicio da aplicación principal ata chegar ao consenso (conéctanse e conectan tres nodos, como no exemplo anterior). Isto dálle á aplicación principal a oportunidade de asumir que cando se inicia, o clúster xa está dispoñible. Sempre que cambie a topoloxía (haberá moitos deles, porque os nodos non se inician de forma totalmente sincrónica), chamarase ao manejador MyApp.Listener.on_state_change/2. A maioría das veces realizamos unha acción cando recibimos unha mensaxe de estado %Cloister.Monitor{status: :up}, que significa: "Ola, o clúster está montado".

Na maioría dos casos, instalación consensus: 3 é óptimo porque aínda que esperemos que se conecten máis nodos, a devolución de chamada pasará status: :rehashingstatus: :up en calquera nodo recentemente engadido ou eliminado.

Cando se inicia no modo de desenvolvemento, só tes que configurar consensus: 1 и Claustro felizmente saltará a espera para a montaxe do cluster cando vexa :nonode@nohostOu :node@hostOu :[email protected] - dependendo de como se configurou o nodo (:none | :shortnames | :longnames).

Xestión de aplicacións distribuídas

As aplicacións distribuídas que non están nun baleiro adoitan incluír dependencias distribuídas, como mnesia. É fácil para nós xestionar a súa reconfiguración desde a mesma devolución de chamada on_state_change/2. Aquí, por exemplo, hai unha descrición detallada de como reconfigurar mnesia sobre a marcha documentación Claustro.

A principal vantaxe de usar Claustro é que realiza todas as operacións necesarias para reconstruír o clúster despois dun cambio de topoloxía debaixo do capó. A aplicación simplemente execútase nun entorno distribuído xa preparado, con todos os nodos conectados, independentemente de que coñezamos os enderezos IP e, polo tanto, os nomes dos nodos de antemán, ou se estes asignaron/modificaron dinámicamente. Isto non require absolutamente ningunha configuración de configuración do docker especial e, desde o punto de vista do programador de aplicacións, non hai diferenza entre executar nun ambiente distribuído ou executar nun local. :nonode@nohost. Podes ler máis sobre isto en documentación.

Aínda que o manexo complexo dos cambios de topoloxía é posible mediante unha implementación personalizada MyApp.Listener, sempre pode haber casos extremos nos que estas limitacións da biblioteca e os prexuízos de configuración resulten ser as pedras angulares da implementación. Está ben, só toma o anterior libcluster, que é de propósito máis xeral, ou incluso xestionar vostede mesmo o clúster de baixo nivel. O obxectivo desta biblioteca de código non é cubrir todos os escenarios posibles, senón utilizar o escenario máis común sen dor innecesaria e copiar e pegar engorroso.

Nota: neste punto do orixinal estaba a frase "Happy clustering!", e Yandex, coa que traduzo (non teño que pasar eu mesmo por dicionarios), ofreceume a opción "Happy clustering!" Quizais sexa imposible imaxinar unha mellor tradución, sobre todo tendo en conta a situación xeopolítica actual.

Fonte: www.habr.com

Engadir un comentario