 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, vengo, estoy actualmente en Berlín con Delibre Giro, es una compañía de comida online, supongo que algunos de vosotros conoceréis la nevera roja, just it, pues es básicamente el mismo negocio, agregamos restaurantes y tú vas a la página web, buscas en tu zona que hay, eliges, pides tu comida y tu comida te llega a casa, puedes pagar online, etcétera. 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 del nivel de holding está en Berlín y actualmente hay 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 que no va a ir esta charla, no vamos a contaros que es un servicio, no vamos a discutir por qué uno podría preferir tener servicios frente a un monolito, no vamos a hablar de como montarlos en una nube, como ponerlos en un contenedor, etcétera, etcétera. 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 en el corrido. Primero vamos a justificarnos 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 background que tenemos con la máquina virtual para ejecutar todo el código, etcétera, 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 cable este servicio, como se comunica con este otro, etcétera, etcétera. 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étera, etcétera, de una forma sencilla. Queríamos que fuera fácil de escalar, es decir, meter nuevas máquinas corriendo nuevos servicios, en mismo servicio, veces adicionales fuera muy sencillo, queríamos que nuestros servicios pudieran comunicarse vía RCP, que pudieran manejar eventos y que pudieran dar servicios, digamos, más externo vía HTTP y todos estos enterarnos que preocupar de montar mucho andamiaje, aunque consideramos que un mínimo nivel de andamios ayuda mucho a estructurar tu código de una forma que sea consistente y legible entre servicios. De todo esto nació el proyecto de LIMF, lo tenemos en open source, podéis encontrar toda la información en LIMF.io, por supuesto aceptamos pull request, etcétera, pero más sobre eso después. Y una vez más que es LIMF, es un framework para hacer servicios en Python, tiene unas dependencias por debajo en su, aunque todo es bastante modular y se podrían sustituir por otras distintas. Por defecto, tenemos, dependemos de Rabbit and Q y su Keeper, no sé si estáis familiarizados con ello, alguien está familiarizado con Rabbit and Q, por favor, en tantas manos. Bueno, para los que no, Rabbit and Q 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 consistentes 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 Jamel con la configuración, básicamente lo primero que hacemos es Import and Live, como bien indica nuestra charla, y luego hacemos una Clash Greeting, que la heredamos del interfaz por defecto de Live 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 donde puede encontrar la clase que implementa dicho interfaz. Este es nuestro pequeño patio de juegos, es una, como ya he dicho, una máquina virtual en Vagrant, con la que tenemos definidas una serie de sesiones en TMAX para poder ver claramente qué está ocurriendo, etcétera, y que la demo funcione sin mayor problema. Todo esto una vez más lo podéis encontrar en ImportLive.link y básicamente sin más vamos a pasar a mostrar un poquito esto, un 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, 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, intentaríamos ver qué comandos tiene, como veis por desgracia la resolución ha quedado un poco pequeña entonces todo parece muy apelotonado, pero como veis el tiene un buen montón de comandos, no vamos a verlos todos pero tampoco os preocupéis de leer demasiado porque los que vamos a ir viendo os los iré contando. Entonces por ejemplo lo siguiente que podríamos hacer sería ver qué servicios están corriendo con linf discover y vemos que hay una instancia del servicio de greeting. Entonces querríamos ver cómo podemos usar este servicio que tiene, 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 podéis 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, servicios, las métricas, etcétera, todo esto viene de serie con un interfaz de linf base. Y ahora vamos a hacer un un recuesta 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 lo Python 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 Europa y Zombilbao. 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 grid, 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. La vez más importamos linf, una vez más se le damos de linf interface y esta vez en lugar de un método RPC lo que decoramos es con escucha eventos de tipo grid. 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 exactamente igual que el anterior, decidimos un nombre para el interfaz y le indicamos la clase en la que donde está la clase en la que puede encontrar la implementación del interfaz y vamos a ver este siguiente ejemplo. Ahora hemos dado un pequeño, bueno primero podéis ver que en el e-sent tenemos ya el evento que ejecutamos antes, como ya he dicho, Revit in 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 gritting. Una vez más vamos a ver qué servicios tenemos levantados, como vemos tenemos dos servicios de gritting y un servicio de leasing, también podéis ver que lanzar los servicios siguesen 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 grid y una vez más el cuerpo del evento tiene que ser un Jason conteniendo el nombre de aquí hemos saludado, Europa y Tom por aquí, luego saludaremos a Europa y Tom por allí y luego quizá Pio, Pio, Pio, como vemos el evento se escucha en el leasing y ahora vamos a verlo trabajar todo junto haciendo un recuesto al servicio de saludo, una vez más Jason 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 leasing, si todo va bien por supuesto, como vemos el saludo lo ha recibido el segundo servicio y si repetimos esto deberíamos ver cómo 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 via HTTP. En este caso no utilizamos linf interface por defectos sino utilizamos uno definido específicamente para servicios web y utilizaremos Berkshoik o algo así para toda la parte de generar las rutas, etcétera. Heredamos de nuestro web service interface, generamos el mapeo de las URL, 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 grito a ese nombre y luego generaremos esto un proxy al servicio de greeting de tal forma que cada vez que se ejecuta puede elegir uno entre los disponibles como vimos antes cuando había múltiples y finalmente devolveremos como despuesta el saludo que hemos recibido del servicio de greeting. En este caso la configuración es un poco más interesante pues no sólo 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 qué 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 la petición http y en algún momento el servicio del isen escucha el evento generado entonces deberíamos ver cómo todos reaccionan ante la petición como no 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 del isen 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étera lo que lo hace bastante complejo a la hora de estar probando cosas en local etcétera pero para ello por suerte linf tiene su propio servidor de desarrollo con lo que hay generando un fichero de configuración punto linf como indicamos podemos definir varias instancias de servicios de instancias de los mismos que queremos lanzar y lanzarlo todo junto con un único comando como vemos aquí pues lanzamos dos procesos de web 3d gritting 4 del isen y nos lo voy a mostrar una vez más como veis al ejecutar el link note hemos levantado hay una serie de servicios vamos a comprobar que es cierto que todos esos servicios están levantados usando el link discover podemos ver que efectivamente hay dos servicios web tres servicios de gritting cuatro del isen y lo que veis a la derecha debajo hemos lanzado linf tail que lo que hace es conectarse a los servicios indicados y escuchar a los 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 ha encontrado loca host tiene sentido como veis en el servidor de desarrollo en el link 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 no entran 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 idis aquí que son consistentes 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 webs en un tres idis definido y los eventos las llamadas rpc etcétera a partir de ahí van todas marcadas con el mismo tres idis 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 pues se hace la petición http la recibe un servidor web consulta con él con el registro que está en su keeper elige uno de los servicios de gritting le envía la petición este ha generado un evento que va 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 del isen existe la posibilidad de definir la escucha de los eventos como como broadcast de tal forma que en lugar de uno de los servicios del isen el evento se ha escuchado por todos ellos una cosa en el efecto secundario de que todos ellos escribirían su escucha y bueno que más da limp 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 su keeper por otro tipo de almacenamiento distribuido tenemos jugs de servicio para ejecutar código cuando arranca su servicio cuando lo paras etcétera de forma de preparación tenemos futuros no siempre quieres que tu llamada remota bloque 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 tiene un ha generado un link top que es como el top del sistema pero específico para los servicios en link 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 del inf básicamente todo lo que transferimos se codifica con message pack que viene a ser json pero más rápido y pequeñito es un formato muy cómodo usamos 0 en q para hacer el rpc usamos su keeper para tener el registro de servicios usamos rabit en q para los eventos usamos y event para generar los greenlets que gestionan cada evento cada llamada remota recibida y para la parte de web utilizamos bergs hoy proyectos similares en ameco son son unos tipos que descubrimos hace un par de meses que tenían un proyecto muy muy parecido al nuestro de hecho estamos muy contentos de haberles 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 linf pero solucionan piezas particulares en bastante buena forma finalmente que espera el futuro del inf estamos creando nuestro propio pequeño ecosistema de librerías para generar servicios particulares como servicios de almacenamiento servicios de monitorización el inflow que es para orquestar flujos de lo que sería proceso de negocios etcétera esperamos en próximos eventos ir desvelando los siguientes pasos según vayamos componiéndolos también en opensource como hemos hecho con linf finalmente pues resumen pues linf es un framework para hacer servicios en python en linf y o podéis encontrar toda la información se aceptan pull requests y esta charla podéis encontrar en import linf punto link y pequeña detalle si alguno quiere mudarse a berlín estamos contratando gente somos un equipo muy entretenido interesante muchas gracias y preguntas una curiosidad el fichero ese de configuración el punto linf donde lo tienes la estructura de carpetas más o menos cómo se organizan si básicamente el fichero punto linf lo tienes en la base donde tengas definidos tus servicios vamos cerrado si básicamente eso lo puedes definir en directorios porque al final los ficheros llaman el de cada servicio te indican que 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 linf 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