We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Deja de pegarte con tus servicios; import lymph

00:00

Formal Metadata

Title
Deja de pegarte con tus servicios; import lymph
Title of Series
Part Number
25
Number of Parts
173
Author
License
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language
Production PlaceBilbao, Euskadi, Spain

Content Metadata

Subject Area
Genre
Abstract
Alejandro Castillo - Deja de pegarte con tus servicios; import lymph ¿Y si pudieras centrarte en la funcionalidad de tus servicios en lugar de programar la integración entre ellos? lymph es un framework con personalidad propia para escribir servicios en Python que te permite hacer justo eso. Incluye descubrimiento de servicios extensible, comunicación vía petición-respuesta, comunicación vía publicación-subscripción extensible y gestión de procesos. A medida que crecen nuestros equipos de desarrollo, nos alejamos cada vez más de una arquitectura monolítica. Queremos empezar a escribir servicios sin tener que preocuparnos de los requisitos de infraestructura. Queremos desarrollar de forma rápida, centrándonos en nuestro trabajo. En esta charla os enseñaremos lo fácil que es desarrollar y ejecutar servicios con lymph.
Keywords
51
68
Thumbnail
39:40
108
Thumbnail
29:48
Library (computing)Service (economics)BitClient (computing)Level (video gaming)Different (Kate Ryan album)Computer architectureMereologyLecture/Conference
Service (economics)BitMultiplication signAdditionLibrary (computing)Presentation of a groupVirtual machineUML
Service (economics)Software frameworkComputer architectureMultiplication signMultiplicationVirtual machineData storage deviceMaxima and minimaSoftware developerLevel (video gaming)Physical systemCodeMultilaterationEvent horizonConfiguration spaceQueue (abstract data type)Internet service providerUML
Demo (music)Interface (computing)CodeService (economics)Computer fileConfiguration spaceDefault (computer science)Social classEvent horizonGame theoryParameter (computer programming)Series (mathematics)TouchscreenJSONUML
Virtual machineBitInstance (computer science)Service (economics)Right angleSeries (mathematics)Interface (computing)Configuration spaceAdditionParameter (computer programming)Image resolutionComputer animation
Social classEvent horizonConfiguration spaceService (economics)Interface (computing)Type theoryImplementation
Event horizonService (economics)Client (computing)Multiplication signHydraulic jumpAnnihilator (ring theory)Instance (computer science)Computer animation
Social classWeb 2.0CASE <Informatik>Multiplication signMereologyProxy serverMappingConfiguration spaceWeb serviceService (economics)TouchscreenComputer animation
Service (economics)Web 2.0Point (geometry)Event horizonWeb serviceComputer animation
1 (number)Configuration spaceFlow separationService (economics)Instance (computer science)Web 2.0WindowSoftware developerSource code
Service (economics)Web serviceLoginWeb 2.0System callSoftware developerSequenceDemo (music)Process (computing)Computer animationSource code
BitPattern languageEvent horizonTelecommunicationSystem callWeb 2.0Dependent and independent variablesServer (computing)Computer animation
BitConfiguration spaceSoftware testingSeries (mathematics)System callLatent heatRemote procedure callClient (computing)Projective planeWeb 2.0MereologyType theoryMetric systemService (economics)Library (computing)Exception handlingDeciphermentElectric generatorCodePlug-in (computing)Data storage deviceGastropod shellEvent horizonError messageDataflowSoftware frameworkQueue (abstract data type)ResultantComputer animation
Point (geometry)Service (economics)Data structureComputer fileClosed setSocial classConfiguration spaceLecture/Conference
Buenas, ante todo gracias por venir, soy Alejandro Castillo, y voy a hablaros un poco de nuestra librería para servicios en Python, que es Lymph, y cómo dejar de pegarte con ellos y simplemente limitarte a hacerlos funcionar. Lo primero, presentarnos un poco, estoy actualmente en Berlín con Delivery Hero, es una compañía de comida online,
supongo que algunos de vosotros conoceréis, La Nebera Roja, Just Eat, es básicamente el mismo negocio, agregamos restaurantes, y tú vas a la página web, buscas en tu zona qué hay, eliges, pidas tu comida y tu comida te llega a casa, puedes pagar online, etc.
Básicamente viene a ser un e-commerce con las particularidades de que el cliente quiere su comida para allá y se cabrea mucho si no come, pero por lo demás no hay grandes diferencias con cualquier otro e-commerce.
Ahora mismo operamos en 34 países, la sede de nivel de holding está en Berlín, y actualmente gran parte de los países operan en sus propias plataformas, que es una de las cosas que esperamos solucionar con nuestra nueva arquitectura de servicios.
Lo primero es contaros un poco de qué no va a ir esta charla, no vamos a contaros qué es un servicio, no vamos a discutir por qué uno podría preferir tener servicios frente a un monolito, no vamos a hablar de cómo montarlos en una nube, cómo ponerlos en un contenedor, etc.
La charla va a estar más centrada en, suponiendo que queremos utilizar servicios, enseñaros nuestra librería para hacer servicios en Python. Este va a ser un poco nuestro recorrido, primero vamos a justificaros por qué hemos creado un framework para esto, en lugar de utilizar herramientas existentes, luego vamos a jugar un poco con el framework, veremos un poco de código,
ejecutaremos unas pocas cosas, luego vamos a entrar un poco en las cosas que no vamos a poder ver en detalle durante la presentación, y finalmente habrá tiempo para preguntas y respuestas. Toda esta charla la podéis encontrar en importlink.link, incluida el Vagrant que tenemos con la máquina virtual para ejecutar todo el código, etc.
Aparte de más detalles en los que no llegamos a entrar durante la charla. Por desgracia la documentación allí está solo en inglés, no he podido traducirla para la charla.
Entonces, lo primero, ¿por qué un framework para servicios en Python? ¿Por qué no utilizar herramientas existentes? Básicamente hará unos dos años y medio, decidimos que queríamos transformar nuestra arquitectura monolítica en una arquitectura basada en servicios,
y queríamos hacerlo de forma que nos generara pocos problemas, que los desarrolladores no tuvieran que pelearse con la infraestructura de servicios en sí, sino que simplemente cada uno pudiera centrarse en que su servicio funcionara y hiciera lo que él quisiera.
Queríamos que ejecutar y testear fuera sencillo, queríamos que no hubiera que preocuparse de la integración, que no tuvieras que preocuparte de qué habla este servicio, cómo se comunica con este otro, etc. Queríamos que la configuración fuera sencilla, pero a la vez nos permitiera definir las cosas lo suficiente
para poder tener múltiples países corriendo en el mismo sistema, múltiples marcas dentro del mismo país, etc. De una forma sencilla, queríamos que fuera fácil de escalar, es decir que meter nuevas máquinas corriendo nuevos servicios en el mismo servicio a veces adicionales fuera muy sencillo, queríamos que nuestros servicios pudieran comunicarse vía RCP,
que pudieran manejar eventos y que pudieran dar servicios más externos vía HTTP, y todo esto sin tenernos que preocupar de montar mucho andamiaje, aunque consideramos que un mínimo nivel de andamio os ayuda mucho a estructurar tu código
de una forma que sea consistente y legible entre servicios. De todo esto nació el proyecto de Linf, que lo tenemos en open source, podéis encontrar toda la información en linf.io, por supuesto aceptamos pull requests, etc., pero más sobre eso después.
Y, una vez más, que es Linf, es un framework para hacer servicios en Python, tiene unas dependencias por debajo, aunque todo es bastante modular y se podrían sustituir por otras distintas, por defecto dependemos de RabbitMQ y su Keeper, no sé si estáis familiarizados con ello,
¿alguien está familiarizado con RabbitMQ? Por favor, levantad manos. Para los que no, RabbitMQ es una cola persistente. Y su Keeper, ¿alguien? Básicamente, su Keeper es un sistema de almacenamiento distribuido de datos clave-valor,
muy sencillito pero bastante consistente, es por lo que lo utilizamos. Bueno, ahora vamos a ver un poco de código y hacer la demo. Vamos a comenzar haciendo un servicio de greeting, que básicamente lo que va a hacer es computar un complejísimo saludo.
Y, sin más, bueno, como veis, va a haber dos ficheros, uno es el propio código que genera nuestro servicio y el otro es un fichero yaml con la configuración. Básicamente, lo primero que hacemos es import Linf, como bien indica nuestra charla.
Y luego hacemos una clase greeting que la heredamos del interfaz por defecto de Linf. Y vamos a decorar un método indicando que es una RPC, que va a ser un método grid para saludar. Vamos a esperar que nos venga el nombre como parámetro. Y básicamente lo que vamos a hacer es sacar por pantalla que estamos saludando a quien sea,
emitir un evento de tipo greeted con el nombre una vez más y devolver ese complejísimo saludo que computamos a la persona adecuada. Como veis, la configuración es muy sencilla, simplemente definimos un nombre para el interfaz que queremos arrancar
y le indicamos dónde puede encontrar la clase que implementa dicho interfaz. Este es nuestro pequeño patio de juegos, es como ya he dicho una máquina virtual en Vagrant en la que tenemos definidas una serie de sesiones en T-Max para poder ver claramente qué está ocurriendo, etc.
y que la demo funcione sin mayor problema. Todo esto, una vez más, lo podéis encontrar en import Linf.link Y básicamente, sin más, vamos a pasar a mostrar un poquito esto en funcionamiento.
Entramos en la máquina y lanzamos ejemplo con el saludo. Como veis, en un lado tenemos a la derecha la instancia que va a estar corriendo el servicio de saludo, el greeting.
Como veis, lanzar la instancia del servicio es bastante fácil, simplemente llamamos a Linf instance con la configuración que hemos definido previamente.
Y en el otro lado tenemos el cliente, que es con lo que vamos a jugar un poco. Suponiendo que no sabemos mucho sobre Linf, intentaremos ver qué comandos tiene. Como veis, por desgracia, la resolución ha quedado un poco pequeña, entonces todo parece estar muy apelotonado. Pero como veis, tiene un buen montón de comandos, no vamos a verlos todos, pero tampoco os preocupéis de leer demasiado,
porque los que vamos serviendo os los iré contando. Entonces, por ejemplo, lo siguiente que podríamos hacer sería ver qué servicios están corriendo con Linf Discover. Ahí vemos que hay una instancia del servicio de greeting.
Entonces, querríamos ver cómo podemos usar este servicio. Para eso tenemos también un comando, que es el Linf Inspect, al que le pasaríamos el nombre del servicio que queremos inspeccionar
y nos mostraría qué cosas podemos ejecutar con él. Os puede sorprender que, además de lo que es el greeting.grid que hemos definido en el código, tenemos también una serie de métodos que vienen de serie con Linf para el propio método que devuelve los datos de la inspección,
un método para hacer ping a servicios, las métricas, etc. Todo esto viene de serie con un interfaz de Linf base. Y ahora vamos a hacer un request a nuestro servicio de greeting. Y, si todo funciona como debe, nos saludará.
Tenemos que enviarle un JSON con el parámetro que quiere, que es el nombre, y vamos a saludar a EuroPython en Bilbao.
En principio lo que esperamos que ocurra es que aquí nos aparezca el saludo que genera el servicio y en el servicio se imprima que estamos saludando a EuroPython en Bilbao. Como vemos, funciona como esperábamos.
Pero esto, por supuesto, es un ejemplo muy pequeño y sencillo de lo que se puede hacer. Como ya hemos visto, al definir el servicio estamos generando unos eventos de este tipo greeted, pero nadie está escuchando esos eventos, no estamos haciendo nada con ellos, entonces vamos a hacer un ejemplo un poquito más interesante añadiendo un servicio que escuche esos eventos.
Una vez más importamos Linf, una vez más elegamos de Linf interface, y esta vez, en lugar de un método RPC, lo que decoramos es con escucha eventos de tipo greeted. El método va a recibir el evento y lo único que va a hacer es indicar que alguien ha saludado a esa persona,
obteniendo el nombre del evento. Una vez más, la configuración es exactamente igual que la anterior, decidimos un nombre para la interfaz y le indicamos dónde está la clase en la que puede encontrar la implementación de la interfaz,
y vamos a ver este siguiente ejemplo. Primero podéis ver que en el Listen tenemos ya el evento que ejecutamos antes,
como ya he dicho Rabbit en Queue es una cola persistente, entonces el evento estaba ahí todavía, y esta vez vamos a dar un pequeño salto de fe y vamos a ver cómo funcionan las cosas teniendo dos servicios de greeting. Una vez más, vamos a ver qué servicios tenemos levantados.
Como vemos tenemos dos servicios de greeting y un servicio de listen. También podéis ver que lanzar los servicios sigue siendo igual de sencillo, simplemente un Linf instance. Y ahora vamos a comprobar qué pasa si emitimos directamente un evento desde la línea de comandos de tipo greeted,
y una vez más el cuerpo del evento tiene que ser un JSON conteniendo el nombre de quien hemos saludado,
Europython por aquí, luego saludaremos a Europython por allí y luego quizá Pio Pio Pio. Como vemos el evento se escucha en el Listen y ahora vamos a verlo trabajar todo junto haciendo un recuesto al servicio de saludo.
Una vez más, JSON con el nombre.
Ahora uno de los dos, no sabemos cuál, la forma en la que está implementado lo que hace es que el propio cliente elige al azar uno de los servicios disponibles, así que uno de los dos recibirá la petición, generará el saludo, emitirá el evento,
y el evento será escuchado en el servicio de listen, si todo va bien por supuesto. Como vemos el saludo lo ha recibido el segundo servicio y si repetimos esto deberíamos ver como en ocasiones lo recibirá un servicio,
en ocasiones otro, se distribuye y Pio Pio Pio. Ahora bien, no estaríamos a estas alturas de siglo sin hablar de web y HTTP,
así que vamos a hacer un ejemplo de un pequeño servicio que sea capaz de comunicarse vía HTTP. En este caso no utilizamos el linfinterface por defecto, sino que utilizamos uno definido específicamente para servicios web y utilizaremos Berkshoyk o algo así para toda la parte de generar las rutas, etc.
Heredamos de nuestro web service interface, generamos el mapeo de las URLs,
en nuestro caso solamente vamos a exponer un SlashGrid que será gestionado por el método grid y el método grid recibirá un request en el que esperamos encontrar el nombre como parámetro, tenemos el nombre del request, vamos a imprimir por pantalla que estamos atendiendo a un grid a ese nombre
y luego generaremos esto es un proxy al servicio de greeting de tal forma que cada vez que se ejecuta se puede elegir uno entre los disponibles como vimos antes cuando había múltiples y finalmente devolveremos como respuesta el saludo que hemos recibido del servicio de greeting.
En este caso la configuración es un poco más interesante pues no solo tenemos que definir el nombre del servicio y la clase en la que lo encontramos sino también el puerto en el que estaremos escuchando. Y vamos a ver que tal se ve todo esto junto, ahora tenemos un servicio de cada
y en teoría si todo esto funciona deberíamos poder hacer un request en el 4080 a grid incluyendo el nombre
y lo que esperamos ahora que ocurra es que el servicio genere una petición HTTP a nuestro servicio web este servicio haga una petición al servicio de greeting, reciba como respuesta el saludo
mientras el servicio de greeting ha emitido un evento, devuelva ese saludo como respuesta a la petición HTTP y en algún momento el servicio de listen escucha el evento generado entonces deberíamos ver como todos reaccionan ante la petición como uno esperaría.
El servicio web ha indicado que iba a hacer una petición al greeting, el greeting ha recibido, ha generado la respuesta que ha sido recibida en el cliente y mientras tanto el servicio de listen ha escuchado el evento y ha actuado en consecuencia.
Como veis cuando empiezas a tener varios servicios las cosas se complican un poco, empiezas a tener muchas ventanas abiertas con instancias de servicios etc. Lo que lo hace bastante complejo a la hora de estar probando cosas en local etc.
pero para ello por suerte Lymph tiene su propio servidor de desarrollo con lo que generando un fichero de configuración punto Lymph como indicamos
podemos definir varias instancias de servicios, instancias de los mismos que queremos lanzar y lanzarlo todo junto con un único comando. Como vemos aquí pues lanzamos dos procesos de web, tres de greeting, cuatro de listen
y os lo voy a mostrar una vez más. Como veis al ejecutar el Lymph Note hemos levantado ahí una serie de servicios. Vamos a comprobar que es cierto que todos esos servicios están levantados
usando el Lymph Discover. Podemos ver que efectivamente hay dos servicios web, tres servicios de greeting, cuatro de listen y lo que veis a la derecha debajo hemos lanzado Lymph Tail que lo que hace es conectarse a los servicios indicados y escuchar a los logs que generan.
De tal forma que vamos a lanzar de nuevo una petición HTTP a nuestro servicio web para que podamos ver lo que ocurre cuando generamos esos logs.
Sí, efectivamente, no he encontrado log host, tiene sentido. Como veréis en el servidor de desarrollo, en el Lymph Note vemos que se produce la secuencia de lo que esperábamos que escribiera cada servicio y en el otro lado se ve muy mal con esta resolución pero se genera un montón de logs.
Hay un problema cuando uno entra a trabajar con servicios y es cómo sigues la ejecución de las cosas. En cuanto hay servicios de por medio es muy complicado saber qué ha pasado, por dónde van las cosas.
Lo que generamos son unos tres IDs aquí que son consistentes, que una vez quedan definidos se propagan en todas las ejecuciones relacionadas con la misma llamada.
Es decir, en este caso, por ejemplo, se define al llegar a la web sin un tres ID definido y los eventos, las llamadas RPC, etcétera, a partir de ahí van todas marcadas con el mismo tres ID de forma que para una única petición se puede seguir lo que ha ocurrido a lo largo de todo el proceso.
Y bueno, eso con suerte termina nuestra demo. Voy a mencionar un poco los patrones de comunicación que se han seguido. Como veis, la petición HTTP la recibe un servidor web,
consulta con el registro que está en su keeper, elige uno de los servicios de greeting, le envía la petición, este ha generado un evento que va a la cola en Rabbit en queue,
ha generado la respuesta, la respuesta se ha devuelto como respuesta a la petición web y el evento ha sido consumido por uno de los servicios de listen. Existe la posibilidad de definir la escucha de los eventos como broadcast, de tal forma que en lugar de uno de los servicios de listen el evento se irá escuchado por todos ellos,
una cosa en efecto secundario de que todos ellos escribirían su escucha. Y bueno, ¿qué más da el Inf?, ya por ir cerrando un poco. Básicamente, como todo juguete, hay que ver que viene en la caja,
tenemos gestión de configuraciones, tenemos utilidades de testeo, las dependencias son configurables, como ya hemos dicho, se podría sustituir Rabbit en queue por otra cola, se podría sustituir Zookeeper por otro tipo de almacenamiento distribuido. Tenemos hooks de servicio para ejecutar código cuando arrancas un servicio,
cuando lo paras, etcétera, de forma de preparación. Tenemos futuros, no siempre quieres que tu llamada remota bloquee, sino que puedes querer devolver un futuro y que se continúe la ejecución mientras se genera el resultado. Generamos métricas que pueden ser consultadas directamente sin nada más.
Se pueden hacer plugins en el sistema, por ejemplo, de serie incluimos un plugin para New Relic y para Sentry, de forma que se pueda monitorizar mejor los servicios. Se pueden generar extensiones del cliente, como por ejemplo, uno de nuestros compañeros ha generado un Lymph Top, que es como el top del sistema,
pero específico para los servicios en Lymph. Errores remotos, puedes hacer que tus servicios generen excepciones y el cliente remoto reciba directamente una excepción en Python en lugar de tener que descifrar mensajes de error, etcétera.
Puedes hacer una shell a un servicio remoto y algunas otras cosas. Estas son las tripas de Lymph. Básicamente todo lo que transferimos se codifica con MessagePack, que viene a ser JSON, pero más rápido y pequeñito.
Es un formato muy cómodo. Usamos SeronQ para hacer el RPC. Usamos SuKeeper para tener el registro de servicios. Usamos Rabbit en Q para los eventos. Usamos Gevent para generar los greenlets que gestionan cada evento,
cada llamada remota recibida. Y para la parte de web utilizamos Berkshoyke. Proyectos similares. Nameco son unos tipos que descubrimos hace un par de meses, que tenían un proyecto muy parecido al nuestro.
De hecho estamos muy contentos de haberlos descubierto, porque valida mucho todo nuestro approach, al haber cogido dos grupos diferentes de personas y solucionado las cosas de forma muy parecida. También dieron una charla ayer, si no la habéis visto, la recomiendo, muy buena.
Y luego hay otra serie de proyectos que no solucionan la globalidad que intentamos solucionar con Lymph, pero solucionan piezas particulares en bastante buena forma. Finalmente, ¿qué espera el futuro de Lymph? Estamos creando nuestro propio pequeño ecosistema de librerías
para generar servicios particulares, como servicios de almacenamiento, servicios de monitorización, el Lymphflow, que es para orquestar flujos
de lo que sería proceso de negocios, etc. Esperamos en próximos eventos ir desvelando los siguientes pasos según vayamos componiéndolos también en open source, como hemos hecho con Lymph. Finalmente, en resumen, Lymph es un framework
para hacer servicios en Python. En Lymph.io podéis encontrar toda la información, se aceptan pull requests y esta charla la podéis encontrar en ImportLymph.link. Y, pequeño detalle, si alguno quiere mudarse a Berlin,
estamos contratando gente, somos un equipo muy entretenido, interesante, muchas gracias. ¿Preguntas? Gracias, Alejandro. ¿Alguna pregunta?
Una curiosidad, ¿el fichero es de configuración en el punto Lymph? ¿Dónde lo tienes? ¿La estructura de carpetas, más o menos, cómo se organizan? Sí, básicamente el fichero punto Lymph lo tienes
en la base donde tengas definidos tus servicios. Vamos. ¿He cerrado? ¿Eh? Sí, básicamente, eso lo puedes definir en directorios, porque, al final, los fichenos yaml de cada servicio te indican
qué estructura seguir para encontrar la clase donde implementas el servicio. Y, básicamente, en la base de tus servicios es donde sueles poner el punto Lymph para poder lanzarlo todo junto de forma cómoda. Bueno, y si no hay más preguntas,
lo podemos dar por terminado. Muchas gracias por asistir y espero que os haya parecido razonablemente interesante.