Historia de la arquitectura Dodo IS: el camino del back office

Habr está cambiando el mundo. Hemos estado blogueando durante más de un año. Hace unos seis meses, recibimos un comentario completamente lógico de Khabrovites: “Dodo, dices en todas partes que tienes tu propio sistema. ¿Y qué es este sistema? ¿Y por qué una cadena de pizzerías lo necesita?

Nos sentamos, pensamos y nos dimos cuenta de que tienes razón. Intentamos explicar todo en nuestros dedos, pero sale en pedazos y en ninguna parte hay una descripción completa del sistema. Así comenzó un largo viaje de recopilación de información, búsqueda de autores y redacción de una serie de artículos sobre Dodo IS. ¡Vamos!

Agradecimientos: Gracias por compartir sus comentarios con nosotros. Gracias a él, finalmente describimos el sistema, compilamos un radar técnico y pronto implementaremos una descripción amplia de nuestros procesos. Sin ti, nos hubiéramos sentado allí por otros 5 años.

Historia de la arquitectura Dodo IS: el camino del back office

Serie de artículos "¿Qué es Dodo IS?" habla de:

  1. Monolito temprano en Dodo IS (2011-2015). (En curso…)
  2. El camino del back office: bases y autobuses separados. (usted está aquí)
  3. El camino del lado del cliente: fachada sobre la base (2016-2017). (En curso...)
  4. La historia de los microservicios reales. (2018-2019). (En curso…)
  5. Aserrado terminado del monolito y estabilización de la arquitectura. (En curso...)

Si está interesado en saber algo más, escriba en los comentarios.

Opinión sobre la descripción cronológica del autor
Regularmente celebro una reunión para nuevos empleados sobre el tema "Arquitectura del sistema". Lo llamamos "Introducción a la arquitectura Dodo IS" y es parte del proceso de incorporación para nuevos desarrolladores. Hablando de una forma u otra de nuestra arquitectura, de sus rasgos, he dado a luz una cierta aproximación histórica a la descripción.

Tradicionalmente, vemos el sistema como un conjunto de componentes (técnicos o de nivel superior), módulos comerciales que interactúan entre sí para lograr algún objetivo. Y si tal punto de vista está justificado para el diseño, entonces no es del todo adecuado para la descripción y la comprensión. Hay varias razones aquí:

  • La realidad es diferente de lo que está en el papel. No todo sale según lo planeado. Y estamos interesados ​​en cómo resultó y funciona realmente.
  • Presentación coherente de la información. De hecho, puede ir cronológicamente desde el principio hasta el estado actual.
  • De lo simple a lo complejo. No universalmente, pero en nuestro caso sí lo es. La arquitectura pasó de enfoques más simples a otros más complejos. A menudo, a través de la complicación, se resolvieron problemas de velocidad y estabilidad de implementación, así como docenas de otras propiedades de la lista de requisitos no funcionales (aquí bien dicho sobre contrastar la complejidad con otros requisitos).

En 2011, la arquitectura Dodo IS se veía así:

Historia de la arquitectura Dodo IS: el camino del back office

Para 2020, se ha vuelto un poco más complicado y se ha vuelto así:

Historia de la arquitectura Dodo IS: el camino del back office

¿Cómo se produjo esta evolución? ¿Por qué se necesitan diferentes partes del sistema? ¿Qué decisiones arquitectónicas se tomaron y por qué? Averigüémoslo en esta serie de artículos.

Los primeros problemas de 2016: por qué los servicios deberían dejar el monolito

Los primeros artículos del ciclo serán sobre los servicios que fueron los primeros en separarse del monolito. Para ponerlos en contexto, les cuento qué problemas tuvimos en el sistema a principios de 2016, que tuvimos que lidiar con la separación de servicios.

Una única base de datos MySql, en la que escribieron sus registros todas las aplicaciones que existían en ese momento en Dodo IS. Las consecuencias fueron:

  • Carga pesada (con el 85% de las solicitudes contabilizadas para lectura).
  • La base ha crecido. Debido a esto, su costo y soporte se convirtieron en un problema.
  • Punto único de fallo. Si una aplicación que escribe en la base de datos de repente comenzó a hacerlo de manera más activa, entonces otras aplicaciones lo sintieron en sí mismas.
  • Ineficiencia en el almacenamiento y consultas. A menudo, los datos se almacenaban en alguna estructura que era conveniente para algunos escenarios pero no adecuada para otros. Los índices aceleran algunas operaciones, pero pueden ralentizar otras.
  • Algunos de los problemas se eliminaron mediante cachés realizados apresuradamente y réplicas de lectura de las bases (este será un artículo aparte), pero solo les permitieron ganar tiempo y no resolvieron el problema fundamentalmente.

El problema era la presencia del propio monolito.. Las consecuencias fueron:

  • Lanzamientos únicos y raros.
  • Dificultad en el desarrollo conjunto de un gran número de personas.
  • Incapacidad para incorporar nuevas tecnologías, nuevos marcos y bibliotecas.

Los problemas con la base y el monolito se han descrito muchas veces, por ejemplo, en el contexto de choques a principios de 2018 (Sea como Munch, o unas pocas palabras sobre la deuda técnica, El día que Dodo se detuvo. Script asíncrono и La historia del pájaro Dodo de la familia Phoenix. La Gran Caída de Dodo ES), por lo que no me extenderé demasiado. Permítanme decir que queríamos dar más flexibilidad al desarrollar servicios. En primer lugar, esto se refería a aquellos que estaban más cargados y eran root en todo el sistema: Auth y Tracker.

El camino de la oficina interna: bases separadas y autobús

Navegación por capítulos

  1. esquema monolito 2016
  2. Comenzando a descargar el monolito: separación de autenticación y rastreador
  3. ¿Qué hace la autenticación?
  4. ¿De dónde son las cargas?
  5. Descarga de autenticación
  6. ¿Qué hace el rastreador?
  7. ¿De dónde son las cargas?
  8. Rastreador de descarga

esquema monolito 2016

Estos son los bloques principales del monolito Dodo IS 2016, y justo debajo hay una transcripción de sus tareas principales.
Historia de la arquitectura Dodo IS: el camino del back office
Entrega de caja. Contabilización de mensajeros, emisión de órdenes a mensajeros.
Centro de contacto. Aceptación de pedidos a través del operador.
Planta. Nuestros sitios web (dodopizza.ru, dodopizza.co.uk, dodopizza.by, etc.).
Auth. Servicio de autorización y autenticación para el back office.
Rastreador. Rastreador de pedidos en la cocina. Servicio para marcar estados de disponibilidad al preparar un pedido.
Caja del Restaurante. Toma de pedidos en un restaurante, interfaces de caja.
Exportar. Subida de informes en 1C para contabilidad.
Notificaciones y facturas. Comandos de voz en la cocina (por ejemplo, “Llegó nueva pizza”) + impresión de facturas para mensajeros.
Jefe de turno. Interfaces para el trabajo del jefe de turno: lista de pedidos, gráficos de rendimiento, transferencia de empleados al turno.
Gerente de oficina. Interfaces para el trabajo del franquiciado y el gerente: recepción de empleados, informes sobre el trabajo de la pizzería.
Marcador de restaurante. Visualización de menús en televisores en pizzerías.
administración. Configuraciones en una pizzería específica: menú, precios, contabilidad, códigos promocionales, promociones, banners del sitio web, etc.
Cuenta personal del empleado. Horarios de trabajo de los empleados, información sobre los empleados.
Tablero de motivación de cocina. Una pantalla separada que cuelga en la cocina y muestra la velocidad de los pizzeros.
Comunicación. Envío de sms y correo electrónico.
Almacenamiento de archivos. Servicio propio de recepción y emisión de archivos estáticos.

Los primeros intentos de solucionar los problemas nos ayudaron, pero fueron solo un respiro temporal. No se convirtieron en soluciones de sistema, por lo que estaba claro que había que hacer algo con las bases. Por ejemplo, para dividir la base de datos general en varias más especializadas.

Comenzando a descargar el monolito: separación de autenticación y rastreador

Los principales servicios que luego registraron y leyeron de la base de datos más que otros:

  1. Aut. Servicio de autorización y autenticación para el back office.
  2. Rastreador. Rastreador de pedidos en la cocina. Servicio para marcar estados de disponibilidad al preparar un pedido.

¿Qué hace la autenticación?

Auth es un servicio a través del cual los usuarios inician sesión en la oficina administrativa (hay una entrada independiente separada en el lado del cliente). También se solicita en la solicitud que se asegure de que los derechos de acceso requeridos estén presentes y que estos derechos no hayan cambiado desde el último inicio de sesión. A través de él, los dispositivos ingresan a la pizzería.

Por ejemplo, queremos abrir una pantalla con los estados de los pedidos terminados en el televisor colgado en el pasillo. Luego abrimos auth.dodopizza.ru, seleccionamos "Iniciar sesión como dispositivo", aparece un código que se puede ingresar en una página especial en la computadora del administrador de turnos, indicando el tipo de dispositivo (dispositivo). El propio televisor cambiará a la interfaz deseada de su pizzería y comenzará a mostrar los nombres de los clientes cuyos pedidos están listos allí.

Historia de la arquitectura Dodo IS: el camino del back office

¿De dónde son las cargas?

Cada usuario registrado de la oficina administrativa va a la base de datos, a la tabla de usuarios para cada solicitud, extrae al usuario a través de una consulta sql y verifica si tiene el acceso y los derechos necesarios para esta página.

Cada uno de los dispositivos hace lo mismo solo con la tabla de dispositivos, comprobando su rol y su acceso. Una gran cantidad de solicitudes a la base de datos maestra conduce a su carga y al desperdicio de recursos de la base de datos común para estas operaciones.

Descarga de autenticación

Auth tiene un dominio aislado, es decir, los datos sobre usuarios, inicios de sesión o dispositivos ingresan al servicio (por el momento) y permanecen allí. Si alguien los necesita, acudirá a este servicio para obtener datos.

ERA. El esquema original de trabajo era el siguiente:

Historia de la arquitectura Dodo IS: el camino del back office

Me gustaría explicar un poco cómo funcionaba:

  1. Una solicitud del exterior llega al backend (hay Asp.Net MVC), trae consigo una cookie de sesión, que se utiliza para obtener datos de sesión de Redis(1). O bien contiene información sobre los accesos, y luego el acceso al controlador está abierto (3,4), o no.
  2. Si no hay acceso, debe pasar por el procedimiento de autorización. Aquí, por simplicidad, se muestra como parte de la ruta en el mismo atributo, aunque es una transición a la página de inicio de sesión. En el caso de un escenario positivo, obtendremos una sesión correctamente completada y pasaremos al Backoffice Controller.
  3. Si hay datos, debe verificar su relevancia en la base de usuarios. ¿Ha cambiado su rol, no debería estar permitido en la página ahora? En este caso, después de recibir la sesión (1), debe ir directamente a la base de datos y verificar el acceso del usuario utilizando la capa lógica de autenticación (2). A continuación, vaya a la página de inicio de sesión o vaya al controlador. Un sistema tan simple, pero no del todo estándar.
  4. Si se pasan todos los procedimientos, saltamos más en la lógica de los controladores y métodos.

Los datos del usuario están separados de todos los demás datos, se almacenan en una tabla de membresía separada, las funciones de la capa lógica de AuthService bien pueden convertirse en métodos API. Los límites del dominio se definen con bastante claridad: usuarios, sus funciones, datos de acceso, concesión y revocación de acceso. Todo mira para que se pueda sacar en un servicio aparte.

CONVERTIRSE EN. Así lo hicieron:

Historia de la arquitectura Dodo IS: el camino del back office

Este enfoque tiene una serie de problemas. Por ejemplo, no es lo mismo llamar a un método dentro de un proceso que llamar a un servicio externo a través de http. Latencia, confiabilidad, mantenibilidad, transparencia de la operación son completamente diferentes. Andrey Morevskiy habló con más detalle sobre tales problemas en su informe. "50 Sombras de Microservicios".

El servicio de autenticación y, con él, el servicio de dispositivos se utilizan para el back office, es decir, para los servicios e interfaces utilizados en producción. La autenticación para los servicios del cliente (como un sitio web o una aplicación móvil) se realiza por separado sin usar Auth. La separación tomó alrededor de un año, y ahora estamos nuevamente tratando este tema, transfiriendo el sistema a nuevos servicios de autenticación (con protocolos estándar).

¿Por qué tomó tanto tiempo la separación?
Hubo muchos problemas en el camino que nos retrasaron:

  1. Queríamos mover los datos de usuario, dispositivo y autenticación de las bases de datos específicas de cada país a una sola. Para hacer esto, tuvimos que traducir todas las tablas y el uso del identificador int al identificador UUId global (recientemente reelaboramos este código Roman Bukin "Uuid - una gran historia de una pequeña estructura" y proyecto de código abierto Primitivas). Almacenar datos de usuario (ya que es información personal) tiene sus limitaciones y para algunos países es necesario almacenarlos por separado. Pero la identificación global del usuario debe ser.
  2. Muchas tablas de la base de datos tienen información de auditoría sobre el usuario que realizó la operación. Esto requería un mecanismo adicional para mantener la coherencia.
  3. Después de la creación de api-services, hubo un largo y gradual período de transición a otro sistema. El cambio tenía que ser fluido para los usuarios y requería trabajo manual.

Esquema de registro de dispositivos en una pizzería:

Historia de la arquitectura Dodo IS: el camino del back office

Arquitectura general después de la extracción del servicio Auth and Devices:

Historia de la arquitectura Dodo IS: el camino del back office

Nota. Para 2020, estamos trabajando en una nueva versión de Auth, que se basa en el estándar de autorización OAuth 2.0. Este estándar es bastante complejo, pero es útil para desarrollar un servicio de autenticación de paso. En el artículo "Sutilezas de la autorización: una descripción general de la tecnología OAuth 2.0» Nosotros, Alexey Chernyaev, tratamos de informar sobre el estándar de la manera más simple y clara posible para que ahorre tiempo al estudiarlo.

¿Qué hace el rastreador?

Ahora sobre el segundo de los servicios cargados. El rastreador cumple una doble función:

  • Por un lado, su tarea es mostrar a los empleados de la cocina qué pedidos están actualmente en el trabajo, qué productos deben cocinarse ahora.
  • Por otro lado, para digitalizar todos los procesos en la cocina.

Historia de la arquitectura Dodo IS: el camino del back office

Cuando aparece un nuevo producto en un pedido (por ejemplo, pizza), va a la estación de seguimiento de Despliegue. En esta estación, hay un pizzero que toma un panecillo del tamaño requerido y lo extiende, luego anota en la tableta de seguimiento que ha completado su tarea y transfiere la base de masa enrollada a la siguiente estación: "Iniciación". .

Allí, el siguiente pizzero llena la pizza, luego anota en la tableta que ha completado su tarea y coloca la pizza en el horno (esta también es una estación separada que debe anotarse en la tableta). Tal sistema estuvo desde el principio en Dodo y desde el principio de la existencia de Dodo IS. Le permite realizar un seguimiento completo y digitalizar todas las transacciones. Además, el rastreador sugiere cómo cocinar un producto en particular, guía cada tipo de producto de acuerdo con sus esquemas de fabricación, almacena el tiempo de cocción óptimo para el producto y realiza un seguimiento de todas las operaciones en el producto.

Historia de la arquitectura Dodo IS: el camino del back officeAsí luce la pantalla de la tablet en la estación del rastreador "Raskatka"

¿De dónde son las cargas?

Cada una de las pizzerías tiene unas cinco tabletas con un rastreador. En 2016 teníamos más de 100 pizzerías (y ahora más de 600). Cada una de las tabletas realiza una solicitud al backend una vez cada 10 segundos y extrae datos de la tabla de pedidos (conexión con el cliente y dirección), composición del pedido (conexión con el producto e indicación de la cantidad), la tabla de contabilidad de motivación (la en él se registra el tiempo de prensado). Cuando un pizzero hace clic en un producto en el rastreador, las entradas en todas estas tablas se actualizan. La tabla de pedidos es general, también contiene inserciones al aceptar un pedido, actualizaciones de otras partes del sistema y numerosas lecturas, por ejemplo, en un televisor que cuelga en una pizzería y muestra los pedidos terminados a los clientes.

Durante el período de lucha con las cargas, cuando todo y todo se almacenaba en caché y se transfería a la réplica asíncrona de la base, estas operaciones con el rastreador continuaron yendo a la base maestra. No debe haber ningún retraso, los datos deben estar actualizados, la falta de sincronización es inaceptable.

Además, la falta de tablas e índices propios sobre las mismas no permitía escribir consultas más específicas y adaptadas a su uso. Por ejemplo, podría ser eficiente para un rastreador tener un índice para una pizzería en una tabla de pedidos. Siempre eliminamos los pedidos de pizzerías de la base de datos del rastreador. Al mismo tiempo, para recibir un pedido, no es tan importante a qué pizzería pertenece, es más importante qué cliente realizó este pedido. Y el medio allí es necesario el índice por el cliente. Tampoco es necesario que el rastreador almacene la identificación del recibo impreso o las promociones de bonificación asociadas con el pedido en la tabla de pedidos. Esta información no es de interés para nuestro servicio de seguimiento. En una base de datos monolítica común, las tablas solo podrían ser un compromiso entre todos los usuarios. Este fue uno de los problemas originales.

ERA. La arquitectura original era:

Historia de la arquitectura Dodo IS: el camino del back office

Incluso después de separarse en procesos separados, la mayor parte del código base siguió siendo común para diferentes servicios. Todo lo que estaba debajo de los controladores era único y vivía en el mismo repositorio. Usamos métodos comunes de servicios, repositorios, una base común, en la que yacen tablas comunes.

Rastreador de descarga

El principal problema con el rastreador es que los datos deben sincronizarse entre diferentes bases de datos. Esta es también su principal diferencia con la separación del servicio Auth, el pedido y su estado pueden cambiar y deben mostrarse en diferentes servicios.

Aceptamos un pedido en la Caja del Restaurante (esto es un servicio), se almacena en la base de datos en el estado "Aceptado". Después de eso, debería acceder al rastreador, donde cambiará su estado varias veces más: de "Cocina" a "Empacado". Al mismo tiempo, algunas influencias externas del cajero o la interfaz del administrador de turnos pueden ocurrir con el pedido. Daré los estados del pedido con su descripción en la tabla:

Historia de la arquitectura Dodo IS: el camino del back office
El esquema para cambiar los estados de los pedidos se ve así:

Historia de la arquitectura Dodo IS: el camino del back office

Los estados cambian entre diferentes sistemas. Y aquí el rastreador no es un sistema final en el que se cierran los datos. Hemos visto varios enfoques posibles para particionar en tal caso:

  1. Concentramos todas las acciones de pedido en un solo servicio. En nuestro caso, esta opción requiere demasiado servicio para trabajar con el pedido. Si nos detenemos en él, obtendríamos el segundo monolito. No solucionaríamos el problema.
  2. Un sistema hace una llamada a otro. La segunda opción ya es más interesante. Pero con él, las cadenas de llamadas son posibles (fallas en cascada), la conectividad de los componentes es mayor, es más difícil de gestionar.
  3. Organizamos eventos, y cada servicio se comunica con otro a través de estos eventos. Como resultado, se eligió la tercera opción, según la cual todos los servicios comienzan a intercambiar eventos entre sí.

El hecho de elegir la tercera opción significaba que el rastreador tendría su propia base de datos, y por cada cambio en el pedido, enviaría un evento sobre este, al que se suscriben otros servicios y que también cae en la base de datos maestra. Para hacer esto, necesitábamos algún servicio que garantizara la entrega de mensajes entre servicios.

En ese momento, ya teníamos RabbitMQ en la pila, de ahí la decisión final de usarlo como intermediario de mensajes. El diagrama muestra la transición de un pedido desde el Cajero del Restaurante hasta el Rastreador, donde cambia su estado y su visualización en la interfaz de Pedidos del Gerente. ACERO:

Historia de la arquitectura Dodo IS: el camino del back office

Ruta de pedido paso a paso
La ruta del pedido comienza en uno de los servicios de origen del pedido. Aquí está el Cajero del Restaurante:

  1. En la caja, el pedido está completamente listo y es hora de enviarlo al rastreador. Se lanza el evento al que está suscrito el rastreador.
  2. El rastreador, al aceptar un pedido por sí mismo, lo guarda en su propia base de datos, generando el evento "Pedido aceptado por el rastreador" y enviándolo a RMQ.
  3. Ya hay varios controladores suscritos al bus de eventos por pedido. Para nosotros es importante el que hace sincronización con una base monolítica.
  4. El controlador recibe un evento, selecciona de él los datos que son significativos para él: en nuestro caso, este es el estado del pedido "Aceptado por el rastreador" y actualiza su entidad de pedido en la base de datos principal.

Si alguien necesita un pedido de los pedidos de la mesa monolítica, también puede leerlo desde allí. Por ejemplo, la interfaz de Pedidos en el Administrador de turnos necesita esto:

Historia de la arquitectura Dodo IS: el camino del back office

Todos los demás servicios también pueden suscribirse para ordenar eventos del rastreador para usarlos por sí mismos.

Si después de un tiempo el pedido se pone en marcha, primero cambia su estado en su base de datos (base de datos Tracker) y luego se genera inmediatamente el evento "OrderIn Progress". También ingresa a RMQ, desde donde se sincroniza en una base de datos monolítica y se entrega a otros servicios. Puede haber varios problemas en el camino, se pueden encontrar más detalles sobre ellos en el informe de Zhenya Peshkov sobre los detalles de implementación de Eventual Consistency en el Tracker.

Arquitectura final después de cambios en Auth y Tracker

Historia de la arquitectura Dodo IS: el camino del back office

Resumiendo el resultado intermedio: Inicialmente, tuve la idea de agrupar los nueve años de historia del sistema Dodo IS en un solo artículo. Quería hablar rápida y simplemente sobre las etapas de la evolución. Sin embargo, sentado por el material, me di cuenta de que todo es mucho más complicado e interesante de lo que parece.

Reflexionando sobre los beneficios (o la falta de ellos) de dicho material, llegué a la conclusión de que el desarrollo continuo es imposible sin anales completos de eventos, retrospectivas detalladas y análisis de mis decisiones pasadas.

Espero que les haya sido útil e interesante conocer nuestro camino. Ahora me enfrento a elegir qué parte del sistema Dodo IS describir en el próximo artículo: escribir en los comentarios o votar.

Solo los usuarios registrados pueden participar en la encuesta. Registrarsepor favor

¿Qué parte de Dodo IS te gustaría conocer en el próximo artículo?

  • 24,1%Monolito temprano en Dodo IS (2011-2015)14

  • 24,1%Primeros problemas y sus soluciones (2015-2016)14

  • 20,7%El camino del lado del cliente: fachada sobre base (2016-2017)12

  • 36,2%La historia de los microservicios reales (2018-2019)21

  • 44,8%Aserrado completo del monolito y estabilización de la arquitectura26

  • 29,3%Sobre futuros planes para el desarrollo del sistema17

  • 19,0%No quiero saber nada de Dodo IS11

58 usuarios votaron. 6 usuarios se abstuvieron.

Fuente: habr.com

Añadir un comentario