Zen Erlang [y Elixir - aprox. traductor

Introducción del traductor


Este artículo trata sobre Erlang , pero todo lo dicho es igualmente aplicable a Elixir , un lenguaje funcional que se ejecuta sobre la misma máquina virtual BEAM . Apareció en 2012 y ahora se está desarrollando activamente. Elixir consiguió la sintaxis más familiar para la mayoría, además de amplias capacidades de metaprogramación , al tiempo que conserva los beneficios de Erlang.


Más del traductor

Un artículo de 2016, pero trata sobre conceptos básicos que no caducan.


Las referencias a conceptos y comentarios míos (el traductor) se encuentran entre corchetes [] y están marcadas con una "nota del traductor".


Si encuentra que algunas partes de la traducción no son lo suficientemente correctas, especialmente en términos de términos, o encuentra algún otro error, hágamelo saber, por favor, lo corregiré con gusto.


Un agradecimiento especial a Jan Gravshin por su ayuda en la revisión y edición del texto.


¿Es esta una transcripción gratuita (o una paráfrasis larga)? De mi presentación en la conferencia ConnectDev'16 organizada por Genetec.


001


Creo que la mayoría de la gente aquí nunca ha programado en Erlang. Es posible que haya oído hablar de él o que conozca el nombre. Por lo tanto, mi presentación afectará solo los conceptos de alto nivel de Erlang, y de tal manera que sea útil en su trabajo o proyectos paralelos, incluso si nunca se encuentra con este idioma.


002


Si alguna vez ha estado interesado en Erlang, entonces escuchó sobre el lema "Let it crash" [ "Let it fall" - aprox. traductor ]. Mi primer encuentro con él me hizo preguntarme de qué demonios se trataba. Se suponía que Erlang era excelente para la ejecución de subprocesos múltiples y la tolerancia a fallas, pero aquí sugieren que deje que todo se caiga: exactamente lo contrario del comportamiento del sistema que realmente quiero. La propuesta es sorprendente, pero, sin embargo, el Zen de Erlang está directamente relacionado con ella.


003


En cierto sentido, usar "Let it Crash" para Erlang es tan divertido como "Blow it up" [ " Blow it !" - aprox. traductor ] para la ciencia de cohetes. "Hacer explotar" es quizás lo último que desea en la ciencia de cohetes, y la catástrofe del Challenger es un vívido recordatorio de esto. Por otro lado, si miras la situación de manera diferente, los cohetes y todo su sistema de propulsión están lidiando con combustibles peligrosos que pueden explotar y explotarán (y este es un momento arriesgado), pero de una manera tan controlada que pueden usarse para organizar el espacio. viajar o enviar cargas útiles a la órbita.


Y el punto aquí está realmente en control; puedes intentar mirar la ciencia de los cohetes como una forma de domar correctamente las explosiones, o al menos su poder, para hacer lo que quieras con ellas. A su vez, puede mirar "Dejar que se bloquee" desde el mismo ángulo: se trata de tolerancia a fallas. La idea no está en las fallas incontroladas generalizadas, es convertir las fallas, las excepciones y los choques en herramientas que se pueden usar.


004


Caída próxima [Caída próxima - aprox. traductor ] y el recocido controlado es un ejemplo real de combatir el fuego con fuego. En Saguenay-lac-Saint-Jean, la región de donde vengo, los campos de arándanos se queman regularmente de manera controlada para ayudar a estimular y reanudar su crecimiento. Muy a menudo, puede ver áreas insalubres del bosque despejadas por incendios para evitar incendios forestales, de modo que esto ocurra bajo la supervisión y el control adecuados. El objetivo principal es eliminar el material combustible para que un fuego natural no pueda extenderse más.


En todas estas situaciones, el poder destructivo del fuego que arrasa los cultivos o los bosques se usa para sanar los cultivos o evitar la destrucción más grande e incontrolada de los bosques.


Creo que el significado de "Let it crash" es exactamente eso. Si podemos aprovechar las fallas, los bloqueos y las excepciones, y hacerlo de una manera manejable, entonces dejarán de ser ese evento aterrador que debe evitarse y, a cambio, se convertirán en un poderoso elemento de construcción para ensamblar grandes sistemas confiables.


005


Por lo tanto, la pregunta es cómo garantizar que las fallas sean más constructivas que destructivas. El chip principal para esto en Erlang es el proceso. Los procesos de Erlang están completamente aislados y tienen una arquitectura inseparable (no comparten nada). Ningún proceso puede arrastrarse a la memoria de otro o afectar el trabajo que realiza distorsionando los datos utilizados. Esto es bueno porque significa que un proceso de muerte con una garantía del 100% mantendrá sus problemas para sí mismo y proporcionará a su sistema un aislamiento de fallas muy fuerte.


Los procesos en Erlang también son extremadamente livianos, por lo que miles y miles de ellos pueden funcionar simultáneamente sin problemas. La idea es utilizar tantos procesos como necesite , en lugar de tantos como pueda permitirse . Imagine que hay un lenguaje de programación orientado a objetos en el que en cualquier momento se le permite tener un máximo de 32 objetos trabajando simultáneamente. Llegaría rápidamente a la conclusión de que para crear programas en él, las restricciones son demasiado estrictas y bastante ridículas. La presencia de muchos procesos pequeños proporciona una mayor variabilidad de averías. En un mundo donde queremos poner el poder de la falla al servicio, ¡eso es bueno!


El mecanismo de los procesos en Erlang puede parecer un poco extraño. Cuando escribe un programa en C, tiene una gran función main() que hace un montón de todo. Este es el punto de entrada al programa. No hay tal cosa en Erlang. Ninguno de los procesos es el principal. Cada proceso inicia una función, y esta función desempeña el papel de main() este proceso en particular.


Ahora tenemos un enjambre de abejas, pero debe ser muy difícil enviarlas para fortalecer la colmena si no pueden comunicarse de ninguna manera. Donde las abejas bailan [las abejas bailan - aprox. traductor ], Erlang procesa mensajes.


006


La mensajería es la forma de comunicación más intuitiva en un entorno competitivo. Es una de las personas más viejas con las que lidiar, desde los días en que escribimos cartas y las enviamos por mensajería a caballo, hasta mecanismos más extraños como los semáforos de Napoleón [ semáforo óptico - aprox. traductor ] que se muestra en la ilustración. En el último caso, simplemente envía un grupo de chicos a las torres, les da un mensaje y agitan banderas para transmitir datos a largas distancias de una manera que era más rápida que los caballos cansados. Poco a poco, este método fue reemplazado por un telégrafo, que, a su vez, cambió el teléfono y la radio, y ahora tenemos todas estas tecnologías de moda para enviar mensajes muy lejos y muy rápido.


Un aspecto extremadamente importante de todos estos mensajes, especialmente en los viejos tiempos, es que todo era asíncrono y los mensajes se copiaron. Nadie estuvo en su porche todo el día esperando que regresara el mensajero y nadie (sospecho) estaba sentado cerca del semáforo, esperando una respuesta. Enviaste un mensaje y volviste a tu negocio, y con el tiempo, alguien te informó que había llegado una respuesta.


Esto es bueno: si el otro lado no responde, no se quedará atrapado en su porche hasta que muera. Por el contrario, el destinatario, por otro lado, no se enfrentará con el hecho de que un mensaje recién llegado ha desaparecido o cambiado mágicamente de repente si usted murió repentinamente. Los datos deben copiarse al enviar mensajes. Estos dos principios aseguran que la falla durante la comunicación no conduzca a un estado distorsionado o irreparable [ estado - aprox. traductor ]. Erlang implementa ambos.


Cada proceso tiene su propio buzón para todos los mensajes entrantes. Cualquiera puede escribir en el buzón de proceso, pero solo el propietario del cuadro tiene la oportunidad de examinarlo. De manera predeterminada, los mensajes se procesan en el orden en que se reciben, pero algunas características como la coincidencia de patrones [ coincidencia de patrones - aprox. traductor ] le permite cambiar las prioridades y centrarse constante o temporalmente en cualquier tipo de mensaje.


007


Algunos de ustedes notarán la extrañeza en lo que digo. Sigo repitiendo que el aislamiento y la independencia son tan maravillosos que los componentes del sistema pueden morir y caer sin afectar al resto. Pero también mencioné la comunicación entre muchos procesos o agentes.


Cada vez que al comienzo del diálogo de dos procesos, aparece una dependencia implícita entre ellos. Un estado implícito surge en el sistema que los conecta a ambos. Si el proceso A envía un mensaje al proceso B, y B muere sin responder, A puede esperar una respuesta para siempre o, después de un tiempo, negarse a comunicarse. La segunda es una estrategia aceptable, pero es muy ambigua: no está completamente claro si el lado remoto ha muerto o ha estado ocupado durante tanto tiempo, y los mensajes sin contexto pueden llegar a su buzón.


A cambio, Erlang nos da dos mecanismos para resolver este problema: monitores y enlaces [ enlaces - aprox. traductor ].


Los monitores tratan de ser un observador. Decide vigilar el proceso, y si muere por algún motivo, un mensaje le notificará lo que sucedió en su bandeja de entrada. Puede responder a esto y tomar decisiones basadas en la información encontrada. El segundo proceso nunca sabrá que hiciste todo esto. Por lo tanto, los monitores son bastante buenos si eres un observador. traductor ] o cuidar el estado de la pareja.


Enlaces [ enlaces - aprox. traductor ] - bidireccional, y la creación de uno combina el destino de ambos procesos relacionados juntos. Cuando un proceso muere, todos los procesos asociados con él reciben un comando para terminar [ señal de salida - aprox. traductor ]. Este equipo, a su vez, mata a otros [ relacionados - aprox. traductor ] procesos.


Todo esto se vuelve realmente interesante, porque puede usar monitores para detectar fallas rápidamente, y puede usar el enlace como un diseño arquitectónico que le permite combinar varios procesos para que la falla se extienda a ellos en su conjunto. Cada vez que mis bloques de construcción independientes se vuelven adictos entre sí, puedo comenzar a agregar esto al programa. Esto es útil porque evita que el sistema se bloquee accidentalmente en estados inestables y parcialmente alterados. Las conexiones garantizan a los desarrolladores: si algo se rompió, se rompió por completo, dejando una hoja en blanco y de ninguna manera afectó a los componentes que no participaron en el ejercicio.


Para esta ilustración, elegí la imagen de escaladores atados con una cuerda de seguridad. Si los escaladores solo están conectados entre sí, se encontrarán en una posición miserable. Cada vez que un escalador se desliza, el resto del equipo morirá de inmediato. No es una buena forma de hacer negocios.


En cambio, Erlang le permite especificar que algunos procesos son especiales y marcarlos con el parámetro trap_exit . Entonces podrán recibir comandos de salida enviados a través de comunicaciones y convertirlos en mensajes. Esto les permitirá solucionar problemas y posiblemente descargar un nuevo proceso para completar el trabajo del difunto. A diferencia de los escaladores, un proceso especial de este tipo no puede evitar que el proceso de asociación se caiga; esto ya es responsabilidad del socio mismo, implementado, por ejemplo, usando try ... catch construcciones try ... catch . El proceso, que captura los resultados, todavía no tiene la oportunidad de jugar en la memoria de otro y guardarlo, pero puede evitar la muerte conjunta.


Esto se está convirtiendo en una oportunidad crucial para crear supervisores. Llegaremos a ellos muy pronto.


008


Antes de pasar a los supervisores, echemos un vistazo a los pocos ingredientes restantes que nos permitirán preparar con éxito un sistema que utiliza gotas para nuestro propio beneficio. Uno de ellos está relacionado con el funcionamiento del planificador de procesos. El caso real al que me gustaría referirme es el alunizaje del Apolo 11 [ Apolo 11 - aprox. traductor ].


Apolo 11 es una misión que fue a la luna en 1969. En la imagen vemos el módulo lunar con Buzz Aldrin y Neil Armstrong a bordo, y creo que la foto fue tomada por Michael Collins, quien permaneció en el módulo de comando.


En el camino hacia el aterrizaje en la luna, el módulo fue controlado por Apollo PGNCS (Sistema primario de guía, navegación y control) [ Apollo PGNCS - aprox. traductor ]. El sistema de control realizó varias tareas con un número de ciclos cuidadosamente calculado [ CPU - aprox. traductor ] cada uno. La NASA también descubrió que el procesador no debe usarse más del 85% de su capacidad, con un 15% libre en stock.


Dado que los astronautas querían tener un plan de respaldo confiable en caso de que tuvieran que interrumpir la misión, dejaron el radar de la reunión con el módulo de comando y servicio activado, sería útil. Esto cargó decentemente la energía restante de la CPU. Tan pronto como Buzz Aldrin comenzó a ingresar comandos, comenzaron a aparecer mensajes sobre sobrecarga y, de hecho, sobre exceder la potencia informática disponible. Si el sistema se hubiera desviado de esto, entonces probablemente no habría podido hacer su trabajo, y todo habría terminado con dos astronautas muertos.


En primer lugar, la sobrecarga se produjo porque el radar tenía un problema de hardware conocido, lo que hacía que su frecuencia no coincidiera con la frecuencia de la computadora de control, lo que condujo a un "robo" de un número de ciclos mucho mayor que el que de otro modo se utilizaría. La gente de la NASA no era idiota y, en lugar de utilizar nuevas tecnologías que no se probaron en la vida real para una misión tan importante, reutilizaron componentes probados, de los cuales conocían errores raros. Pero, lo que es más importante, se les ocurrió una programación prioritaria.


Esto significa que cuando este radar, o tal vez los comandos ingresados, ponen demasiada carga en el procesador, sus tareas se anulan para dar ciclos de CPU a las cosas vitales que tienen una prioridad más alta y realmente las necesitan. Fue en 1969. Hoy en día hay muchos más lenguajes y marcos que ofrecen solo despacho cooperativo y nada más.


Erlang no es un lenguaje que deba usarse para sistemas vitales, solo tiene en cuenta las restricciones suaves en tiempo real : aprox. traductor ], y no restricciones estrictas en tiempo real, y por lo tanto, usarlo para tales escenarios no sería una buena idea. Pero Erlang proporciona una planificación proactiva [ es una planificación preventiva, aprox. traductor ] y priorización de procesos. Esto significa que usted, como desarrollador o arquitecto de sistemas, no tiene que preocuparse de que, para evitar congelamientos, absolutamente todos calculen cuidadosamente la carga de CPU requerida para sus componentes (incluidas las bibliotecas utilizadas). Simplemente no pueden obtener tal poder. Y si desea que se realice alguna tarea importante cuando la necesite, también puede proporcionarla.


Esto no parece una demanda seria o frecuente, y las personas aún lanzan proyectos realmente exitosos basados ​​únicamente en la programación cooperativa de procesos paralelos, pero ciertamente es extremadamente valioso, ya que lo protege de los errores de otras personas, así como de los suyos. También abre la puerta a mecanismos como el equilibrio de carga automático, "castigar mal" o "alentar procesos buenos", o asignar prioridades más altas a procesos con más tareas. Todo esto finalmente hace que sus sistemas sean lo suficientemente adaptables a cargas y eventos imprevistos.


009


El último componente que me gustaría discutir como parte de garantizar una resiliencia decente es la capacidad de trabajar en la red. En cualquier sistema que se desarrolle teniendo en cuenta la actividad a largo plazo, la capacidad de ejecutarse en más de una computadora se convierte rápidamente en un requisito obligatorio. No querrás sentarte en un lugar cerrado detrás de las puertas de titanio con tu automóvil dorado, sin poder compensar las fallas que afectan principalmente a tus usuarios.


Tarde o temprano necesitará dos computadoras, de modo que una sobreviva a la falla de la segunda, y posiblemente la tercera, si desea implementar parte de su sistema durante fallas.


El avión en la ilustración - F-82 Twin Mustang [ F-82 Twin Mustang - aprox. traductor ], un avión diseñado durante la Segunda Guerra Mundial para escoltar bombarderos a distancias que la mayoría de los otros combatientes simplemente no podían cubrir. Tenía dos cabañas, para que los pilotos pudieran controlar el dispositivo por turnos; en el momento adecuado, fue posible dividir las responsabilidades para que un piloto pudiera volar el avión, y el segundo control de radares en el papel de interceptor. Los aviones modernos aún tienen capacidades similares; tienen innumerables sistemas duplicados y, a menudo, los miembros de la tripulación duermen durante el vuelo, por lo que siempre hay alguien listo, si es necesario, para hacerse cargo inmediatamente del control de la aeronave.


En cuanto a los lenguajes de programación o entornos de desarrollo, la mayoría de ellos están diseñados sin la posibilidad de trabajo distribuido, aunque está claro que al desarrollar una pila de servidores, deberá trabajar con más de un servidor. Sin embargo, si va a trabajar con archivos, hay herramientas para esto en la biblioteca estándar. Lo máximo que la mayoría de los idiomas pueden darle es el soporte de socket o un cliente HTTP.


Erlang rinde homenaje a la realidad de los sistemas distribuidos y ofrece una implementación para su creación, que es documentada y transparente. , , - [ pylyglot systems — . ].


010


" ". - , . "Let it crash" , , .


— .


011


[ supervision trees — . ] — , . — , — — , . , — "OTP", , "Erlang/OTP" [ OTP — Open Telecom Platform — . ].


— , , , , , "" . , : , , .


, , , , — .


012


. " , ". , . .


. " " [ one for one — . *]. . , .


— " " [ one for all — . *]. , . , , . , . , . , , . , , !


, , , . , . : , .


, . — " " [ rest for one — . ]. , , . .


[ , — — . ] . 1 , 150 .


013


, , " , !"


. , , , . "" [ — . ] "" [ — . ], Jim Gray 1985 ( Jim Gray, !)


-, — , , . . , , . , , , , .


— , , , . , , . , , .


, , .


014


, — .


, . , , .


, — , , . , — ; . , , . , , , .


, , .


. , , [ Property-Based Testing Basics , Property-based testing — . ] ( ), — - , . , , , .


015


( ). , , .


, . , , , , . - -.


. , , , , , , .


, . Jim Gray, , , 132 , , . 131 132 , , . , , , , ; , , , 100 000 , — 10 , - .


, , .


016


?


, . . , . , , . , "" Facebook ( ), , , Facebook .


, , , , . , , .


, . : , , , , .


, ( ), , . , .


017


, , . , , , .


, , .


018


() . , : . Tally () , Live Reports ( ) .


, . District (; ) , (Storage). (Cache) ( ) (Worker pool).


[ supervision strategies — . ], , , , . , " ", , , . ( ) " ". , (OCR) , , . , , , , .


OCR , C , . , C, , , .


, , , . 10 , , , .


, , . , . — , .


, , , . OCR C , . OCR . . , , ( ). , , — , .


OCR , . , , — . — . , , , , - , .


, . , — - , - ( ) , . , — , . — let it crash!


. , if/else , switch ', try/catch . , , , . [ , — . ], .


019


, , , , . : , .


, , , . (, SMS).


, , , , , .


020


OTP. OTP- — , . , , . , , , . , , , .


, OTP- . OTP-, . [: OTP-, , ]


:


  • , ;
  • , , , ;
  • , ;
  • , , , , ;
  • ( , );
  • .

. , . , , . , — , , .


021


, ? , . , Heroku .


. (vegur) , , , . , , .


- , . , : 500 000 1 000 000 ! , . ? , , , 100 000 , ? - 1:17000 1:7000. , , , .


, . , , , . , . , , .


022


. .


, - : " , . , , , . , , . , ."


. .


, , , 60 . ( United 734), , , , - . , , , , ABS, .


( ), . , . , , .


023


, . ( , ) Richard Cook. , YouTube, .


- . , , , .. — ( , , ..) , , - , .


, , , . , , - - .


, , , . , . , . - - , , , .


024


, . , , : , . . , , , .


, , , . .


025


, , . , , , .


. , , , - , , , , , . , .


026


, 'let it crash' — , , , , , — , , , . . fail-fast , , " ", .


, . , , . . , , . Let it crash.


027


: , , , — . , ( , !) .

Source: https://habr.com/ru/post/443290/


All Articles