Home Microservicios en Nu: un...

Microservicios en Nu: un vistazo a nuestra ingeniería de software

Conoce acerca de lo que hemos aprendido al hacer crecer un sistema complejo de ingeniería durante los primeros ocho años de Nu.

Ingeniero de software de Nu México con las manos en la cabeza nos habla de los Microservicios en Nu

En Nu buscamos evolucionar constantemente, ofreciendo a la comunidad morada una experiencia más simple y eficiente cada vez. Para lograrlo, ponemos mucha atención en los aprendizajes que nos llevamos en el camino. Hoy queremos platicarte sobre lo que hemos aprendido en el rubro de tecnología financiera, al crecer el sistema que sostiene a Nu. Explicaremos la estructura que tenemos, así como los retos que hemos enfrentado con los microservicios: un estilo arquitectónico que se coloca como uno de los grandes favoritos en la industria de la tecnología financiera. 

Y quién mejor para explicarlo que nuestro #CodeStar Alex Aldazabal, Senior Software Engineer en Nu México, para llevarnos por este universo, ya que además, es uno de los protagonistas de esta gran historia.

El principio de los microservicios en Nu

Ocho años, de 2013 a 2021, es también toda la vida útil de la empresa, lo que significa que comenzamos con microservicios desde el primer día, desafiando el consejo estándar de comenzar con una arquitectura monolítica.

Este consejo se debe a que es más fácil empezar con un diseño que maneje todas las responsabilidades desde el inicio, mientras el negocio puede salir al mercado y ofrecer un producto a sus clientes. Luego de contar con un producto se piensa en refactorizar la arquitectura original a una más estable y escalable, muchas veces este momento demora en llegar.

Descubrimos que era cierto que comenzar con los microservicios, particularmente en 2013, nos hizo más lentos al principio. Armar una infraestructura de aprovisionamiento compleja mientras se construye el producto desde cero fue mucho para un equipo pequeño, y tomó algo de tiempo hasta que sentimos que el trabajo fluía sin problemas. Por otro lado, nuestro negocio no estaba muy inclinado a los cambios rápidos y esos primeros meses fueron probablemente el mejor momento para invertir en una base sólida.

Eso no quiere decir que hicimos todo bien desde el principio. Por el contrario, tuvimos que cambiar muchas de nuestras abstracciones centrales a medida que entendíamos el dominio con más profundidad, lo que a veces significaba que teníamos que volver a trazar las responsabilidades que cada servicio debía tener. Este proceso de aprendizaje continúa hasta el día de hoy. En un momento dado, un equipo u otro trabajará para dividir un servicio o fusionar dos servicios.

¿Conoces las posiciones de ingeniería que están abiertas en Nu? Da clic en los siguientes enlaces y aplica para transformarte en un #CodeStar:

Mobile Software Engineer

Software Engineer 

Senior Software Engineer

Aprovisionamiento e implementación

Nuestra infraestructura de producción pasó por varios cambios. Comenzamos con un servicio de Chef administrado, experimentamos con CoreOS Fleet y ECS, construimos una infraestructura simple de un contenedor por vm utilizando abstracciones centrales de AWS EC2 y CloudFormation, para finalmente converger en la implementación de nuestros propios clústeres de Kubernetes. Fue un viaje largo pero mucho menos arduo debido a la automatización generalizada.

Todos nuestros recursos en la nube, desde el principio, se aprovisionan a través de algún tipo de proceso automatizado. Incluso los únicos, como esa instancia de livegrep que un escuadrón quería comenzar a funcionar en poco tiempo, deben automatizarse.

Como la mayoría de las cosas en la empresa, nuestra obsesión por la automatización es mucho más una norma cultural que una regla impuesta.

La última encarnación de nuestra infraestructura de automatización toma la forma de una base de código Clojure que organiza la creación de recursos de AWS o Kubernetes. Una entrada crítica para ese proceso proviene de un repositorio de git donde el equipo de ingeniería colabora para declarar metadatos para cada microservicio: qué tipo de base de datos requiere, qué tan pesada es la carga de trabajo, qué tipo de herramientas de compilación y prueba se deben pasar durante la compilación, etc.

Sobre la base de estos datos, nuestra automatización puede hacer magia como aprovisionar bases de datos, configurar el descubrimiento de servicios e incluso conjurar canales de compilación completos para todos los servicios.

Infraestructura inmutable

Gran parte de nuestra cultura de ingeniería está conectada con la comunidad y las ideas de programación funcional. Una idea central es el concepto de inmutabilidad: siempre es más seguro crear copias actualizadas de los datos que cambiarlos.Cuando trasladamos esta vista al dominio de la infraestructura, se traduce en la creación de copias actualizadas de los recursos en lugar de mutarlos.

Una aplicación simple de este principio se aplica a la implementación: primero ponemos en marcha nuevos contenedores para luego derribar las instancias antiguas. Nada particularmente interesante allí: un ejemplo bastante estándar de técnicas azul-verde.

Una aplicación a mayor escala requiere crear nuevas particiones en producción. De vez en cuando, tenemos que hacer cambios que son más grandes que una simple implementación. Podríamos estar reforzando la seguridad, mejorando el descubrimiento de servicios o ajustando el tamaño de los elementos de infraestructura. Independientemente de los detalles, el enfoque general es el mismo.

Aprovisionamos una partición completa en producción, incluidos todos los servicios, clústeres de Kubernetes, clústeres de Kafka, etc., probamos si está funcionando bien y luego dirigimos el tráfico a la nueva partición actualizando los alias de DNS de todos los puntos de entrada. No hace falta decir que todo este proceso está muy automatizado, hasta el punto de que un pequeño equipo puede ejecutar todos los pasos cada dos meses.

¿Quieres conocer a fondo las vacantes disponibles en ingeniería Nu? Da clic en los siguientes enlaces:

Mobile Software Engineer

Software Engineer 

Senior Software Engineer

Servicio de comunicación y mensajería asincrónica

Cuidar las finanzas de las personas y ayudarlas a hacer más con su dinero, es una misión que nos tomamos muy en serio. En consecuencia, la integridad de los datos es de suma importancia. Ejecutar un service mesh mientras se mantienen esos altos estándares trae nuevos desafíos: ¿cómo garantizar que los datos nunca se pierdan en un mundo donde las fallas parciales y las particiones de red son la norma? Nuestra respuesta es confiar en gran medida en la mensajería asincrónica.

La mayoría de las interacciones de servicio a servicio son intermediadas por un message broker. En lugar de hacer que el cliente espere a que el servidor termine de procesar y responda, sujeto a todo tipo de fallas debido a desequilibrios de carga, fallas en la red y similares, el productor enviará de manera confiable un mensaje que luego será consumido por el siguiente servicio en el flujo.

Aún pueden ocurrir fallas. Imagina que, para procesar un mensaje, el consumidor necesita realizar una llamada a un servicio de terceros que tiene problemas de estabilidad. Incluso entonces, podemos recuperar y evitar la pérdida de datos detectando el error en una capa inferior y redireccionando automáticamente el mensaje a un dead letter.

Extracción de datos y toma de decisiones

Además de los aspectos operativos que hemos cubierto hasta ahora, debemos considerar las necesidades de datos para la toma de decisiones en la empresa. Los responsables de la toma de decisiones, incluidos los analistas de negocios y los científicos de datos, dependen de los datos que escribieron los microservicios para sus modelos. Nuestro objetivo como ingenieros es ofrecerles una interfaz estable para esos datos.

Esto es un desafío, dado que los modelos de datos siempre están cambiando. Además, nuestros datos se particionan para manejar la escalabilidad; en general, los datos son demasiado complejos para que del lado analítico puedan trabajar con ellos.

Hace unos años, implementamos una capa llamada ‘contratos’ para resolver el problema. Los contratos sirven como una interfaz estable mencionada anteriormente. Mediante contratos, podemos exponer de forma segura los datos de microservicios al lado analítico de la empresa y reducir el riesgo de romper modelos silenciosamente. Los contratos son objetos de Scala generados automáticamente a partir del modelo de datos de servicio.

Con los contratos, nuestros batch jobs de Spark transforman los datos en tablas destinadas a cumplir con cualquier propósito analítico posterior. Para asegurarnos de que esta capa refleje consistentemente la realidad, dependemos en gran medida de las pruebas automatizadas, tanto para los servicios como para los jobs de Spark.

Debido a las pruebas, rara vez nos encontramos con problemas debido a cambios en el esquema de datos que interrumpen el análisis. Sin embargo, todavía luchamos por reaccionar de manera apropiada a los cambios de los ‘valores de datos’ en los orígenes de datos. Esto puede suceder cuando la definición de un dato cambia mientras que el análisis posterior no es consciente de ello.

Actualmente estamos atacando este problema desde varios ángulos, como la detección de anomalías en las estadísticas de la tabla (conteo, cardinalidad, etc.), mejorando la comunicación entre ingenieros y los stakeholders, y desacoplando contratos y casos de uso analítico (implementación de almacén de datos). Sin embargo, todavía está lejos de ser un problema resuelto.

Microservicios en Nu: Conclusión

Hay mucho más de lo que podemos hablar. Desde otros patrones de confiabilidad que hemos aplicado a lo largo de los años hasta los detalles de nuestro viaje de orquestación de contenedores. La forma en que planeamos la escalabilidad con particiones hasta la cultura de aprender de las caídas a través de los postmortems sin culpas.

Nuestras experiencias en la construcción de back-ends para nuestros front-ends hasta … bueno, te haces una idea. Esto es demasiado para una sola publicación de blog, pero suficiente para darse una idea del camino recorrido por el equipo de ingeniería en Nu, el cual seguirá evolucionando para simplificar la vida financiera de las personas.

Atrévete a formar parte de esta revolución morada, checa aquí las vacantes para unirte a nuestro equipo de ingeniería. Aplicas dando clic sobre cada una de las posiciones:

Mobile Software Engineer

Software Engineer 

Senior Software Engineer

Si quieres conocer más sobre la ingeniería de software móvil en Nu, habla con Alex, haz clic aquí para contactarlo.

Este contenido es parte de la misión de Nu para devolver a las personas control sobre sus vidas financieras. ¿Aún no conoces Nu? Obtén más información sobre nuestro servicio y nuestra tarjeta de crédito sin complicaciones, da clic aquí.

Introduzca su nombre