Notas sobre Microservicios en Elixir

El dia de ayer asistí a la reunión del grupo de Elixir Monterrey donde se habló de Microservicios co-organizada por ecaresoft. Gracia a ellos y los presentadores por el tiempo dedicado.

Me gustó que a pesar de vender la idea de los Microservicios esto se hizo con cautela. Tanto quienes presentaron como algunos asistentes advirtieron de los riesgos de subirse al tren de los microservicios antes de tiempo.

Me gustó que se dejó claro que existe más de una forma de lograr una arquitectura de microservicios.

Me gustó que se trivializaron los microservicios. No sé les trató como algo complicado o dificil y eso ayuda a desmitificarlo para los novatos. El mismo Valim ha llegado a decir que dado BEAM nos permite tener nanoservicios de forma gratuita y trivial (en comparación con otros lenguajes y frameworks).

Algo que me gustaría comentar al respecto de la charla es sobre el ejemplo práctico que se dió.

En el ejemplo se mostró una microservicio creado de Elixir que corría sobre plug/cowboy con serialización con JSON.

Si bien esto tiene sentido comunicación entre procesos donde hay variedad de lenguajes involucrados, para un caso en el que solamente existe Elixir agregar una serie de dependencias solamente para lograr comunicación entre procesos es completamente innecesario.

El BEAM nos permite ejecutar código en otros nodos sin tener que preocuparnos por el medio ni la serialización. Crear un API con JSON para lograr eso es superfluo. Quiero creer que el ejemplo se hizo con fines didácticos :)

Ahora, hay quienes terminan implementando APIs en HTTP (como la del ejemplo) porque de esa forma pueden hacer uso del sistema de dispatching/load balancing que probablemente ya tienen. Pero esto se puede lograr de otras formas, como por ejemplo con el módulo de pg2.

Actualización

Me han preguntado via twitter por alguna referencia de “cómo hacer la serialización/comunicación automática”.

Es posible que ya sepan la respuesta y que éste post los haya confundido haciéndoles pensar que hay una técnica que permite lograr esto.

Pero no hay una técnica per se sino que solamente tenemos que usar lo que la BEAM nos ofrece.

Si tuvieramos un monolito en Ruby y quisiéramos dividirlo en dos, casi que por impulso lo que haríamos sería lograr que las dos nuevas partes se comunicaran via HTTP, probablemente serializando a JSON.

Esta solucíon implica varias cosas:

- elegir un transporte (HTTP)
- elegir un método de serialización (JSON)
- implementar una estrategia de fallas/reintentos
- necesidad de tener una herramienta que haga load balancing
- ahora hay que administrar 2 procesos/repositorios
- hay que sincronizar los 2 proyectos cuando haya cambios en esta conexión

Practicamente casi todo eso lo resuelve el BEAM. El BEAM nos permite hacer llamadas síncronas o asíncronas a otros nodos (ya sea en la misma máquina) o en otra. La guía de Elixir trae un ejemplo de cómo usar spawn_link para arrancar y ejecutar código en otro nodo.

Módulos como pg2 construyen sobre esto y nos permiten tener un catálogo de procesos a donde tu código va y se registra. Por ejemplo, supongamos que tienes dos procesos que hacen autorizaciones de tarjetas de crédito. Esos procesos van y se registran al catálogo como :procesadores_de_tdc. El código que tiene que mandar autorizar tarjetas solamente tiene que ir a ese catálogo y agarrar al azar a un proceso del grupo :procesadores_de_tdc y luego mandarle un mensaje. Y listo.

Por otro lado. Asumiendo que encuentran una razón de muchísimo peso para separar el código en microservicios. Y lo hacen de forma que terminan con 2 repositorios (algo que creo que es lo más común). En este punto yo lo pensaría dos veces. Es innecesario separar el código en dos. Simplemente mantengan el monolito y cuando hagan 1 deploy por microservicio. Uno de ellos hace una cosa y el otro la otra. No tienen que ser repositorios diferentes.