"Camiñando cos meus zapatos" - espera, están marcados?

Desde 2019, Rusia ten unha lei sobre a etiquetaxe obrigatoria. A lei non se aplica a todos os grupos de produtos, e as datas para a entrada en vigor da etiquetaxe obrigatoria para os grupos de produtos son diferentes. O tabaco, o calzado e os medicamentos serán os primeiros en ser obxecto de etiquetaxe obrigatoria; despois engadiranse outros produtos, por exemplo, perfumes, téxtiles e leite. Esta innovación lexislativa provocou o desenvolvemento de novas solucións informáticas que permitirán facer un seguimento de toda a cadea de vida dun produto, desde a produción ata a compra polo consumidor final, ata todos os participantes no proceso: tanto o propio Estado como todas as organizacións que venden bens con etiquetaxe obrigatoria.

En X5, o sistema que rastrexará os produtos etiquetados e intercambiará datos co estado e os provedores chámase "Marcus". Imos dicirche por orde como e quen o desenvolveu, cal é a súa pila tecnolóxica e por que temos algo do que estar orgullosos.

"Camiñando cos meus zapatos" - espera, están marcados?

Alta carga real

"Marcus" resolve moitos problemas, o principal é a interacción de integración entre os sistemas de información X5 e o sistema de información estatal para produtos etiquetados (GIS MP) para rastrexar o movemento dos produtos etiquetados. A plataforma tamén almacena todos os códigos de etiquetaxe que recibimos e todo o historial do movemento destes códigos entre obxectos e axuda a eliminar a recalificación dos produtos etiquetados. Usando o exemplo dos produtos do tabaco, que foron incluídos nos primeiros grupos de produtos etiquetados, só un camión cargado de cigarros contén uns 600 paquetes, cada un dos cales ten o seu propio código único. E a tarefa do noso sistema é rastrexar e verificar a legalidade dos movementos de cada un destes paquetes entre almacéns e tendas e, en definitiva, verificar a admisibilidade da súa venda ao comprador final. E rexistramos unhas 000 transaccións en efectivo por hora, e tamén necesitamos rexistrar como cada un destes paquetes entrou na tenda. Así, tendo en conta todos os movementos entre obxectos, agardamos decenas de miles de millóns de rexistros ao ano.

Equipo M

A pesar de que Marcus se considera un proxecto dentro de X5, estase implementando mediante un enfoque de produto. O equipo traballa segundo Scrum. O proxecto comezou o verán pasado, pero os primeiros resultados chegaron só en outubro: o noso propio equipo estaba totalmente montado, desenvolveuse a arquitectura do sistema e comprouse o equipo. Agora o equipo conta con 16 persoas, seis das cales están implicadas no desenvolvemento de backend e frontend, tres das cales están implicadas na análise do sistema. Seis persoas máis están involucradas nas probas manuais, de carga, automatizadas e de mantemento do produto. Ademais, contamos cun especialista en SRE.

Non só os desenvolvedores escriben código no noso equipo; case todos os mozos saben como programar e escribir autotests, cargar scripts e scripts de automatización. Prestamos especial atención a isto, xa que incluso o soporte de produtos require un alto nivel de automatización. Sempre procuramos aconsellar e axudar aos compañeiros que non teñen programado antes, e darlles pequenas tarefas para traballar.

Debido á pandemia de coronavirus, trasladamos a todo o equipo ao traballo remoto; a dispoñibilidade de todas as ferramentas para a xestión do desenvolvemento, o fluxo de traballo construído en Jira e GitLab permitiron pasar facilmente esta etapa. Os meses pasados ​​a distancia demostraron que a produtividade do equipo non se resentiu, para moitos aumentou a comodidade no traballo, o único que faltaba era a comunicación en directo.

Reunión de equipo a distancia

"Camiñando cos meus zapatos" - espera, están marcados?

Reunións durante o traballo remoto

"Camiñando cos meus zapatos" - espera, están marcados?

Pila tecnolóxica da solución

O repositorio estándar e a ferramenta CI/CD para X5 é GitLab. Usámolo para almacenamento de código, probas continuas e implantación en servidores de proba e produción. Tamén utilizamos a práctica da revisión do código, cando polo menos 2 compañeiros necesitan aprobar os cambios realizados polo programador no código. Os analizadores de código estático SonarQube e JaCoCo axúdannos a manter o noso código limpo e a garantir o nivel necesario de cobertura das probas unitarias. Todos os cambios no código deben pasar por estas comprobacións. Todos os scripts de proba que se executan manualmente automatízanse posteriormente.

Para a implantación exitosa dos procesos de negocio por parte de "Marcus", tivemos que resolver unha serie de problemas tecnolóxicos, cada un en orde.

Tarefa 1. A necesidade de escalabilidade horizontal do sistema

Para resolver este problema, escollemos un enfoque de microservizos para a arquitectura. Ao mesmo tempo, era moi importante comprender as áreas de responsabilidade dos servizos. Intentamos dividilos en operacións comerciais, tendo en conta as especificidades dos procesos. Por exemplo, a aceptación nun almacén non é unha operación moi frecuente, pero a gran escala, durante a cal é necesario obter rapidamente do regulador estatal información sobre as unidades de mercadorías que se aceptan, cuxo número nunha entrega alcanza os 600000. , comprobar a admisibilidade de aceptar este produto no almacén e devolver toda a información necesaria para o sistema de automatización do almacén. Pero o envío desde almacéns ten unha intensidade moito maior, pero ao mesmo tempo opera con pequenos volumes de datos.

Implementamos todos os servizos sen estado e mesmo tratamos de dividir as operacións internas en pasos, utilizando o que chamamos temas propios de Kafka. Isto é cando un microservizo envíase unha mensaxe a si mesmo, o que lle permite equilibrar a carga en operacións máis intensivas en recursos e simplifica o mantemento do produto, pero máis sobre iso máis tarde.

Decidimos separar os módulos para a interacción con sistemas externos en servizos separados. Isto permitiu resolver o problema das APIs de sistemas externos que cambian con frecuencia, sen que practicamente ningún impacto nos servizos con funcionalidade empresarial.

"Camiñando cos meus zapatos" - espera, están marcados?

Todos os microservizos están implantados nun clúster OpenShift, o que resolve tanto o problema de escalar cada microservizo como nos permite non utilizar ferramentas de descubrimento de servizos de terceiros.

Tarefa 2. A necesidade de manter unha carga elevada e un intercambio de datos moi intenso entre os servizos da plataforma: Só durante a fase de lanzamento do proxecto realízanse unhas 600 operacións por segundo. Esperamos que este valor aumente a 5000 operacións/s a medida que os puntos de venda se conecten á nosa plataforma.

Este problema resolveuse implantando un clúster de Kafka e abandonando case por completo a interacción sincrónica entre os microservizos da plataforma. Isto require unha análise moi coidadosa dos requisitos do sistema, xa que non todas as operacións poden ser asíncronas. Ao mesmo tempo, non só transmitimos eventos a través do corredor, senón que tamén transmitimos toda a información comercial necesaria na mensaxe. Así, o tamaño da mensaxe pode chegar a varios centos de kilobytes. O límite de tamaño da mensaxe en Kafka esixe que predigamos con precisión o tamaño da mensaxe e, se é necesario, dividímolo, pero a división é lóxica, relacionada coas operacións comerciais.
Por exemplo, dividimos as mercadorías que chegan nun coche en caixas. Para as operacións síncronas, asígnanse microservizos separados e realízanse probas de carga exhaustivas. Usar Kafka presentounos outro reto: probar o funcionamento do noso servizo tendo en conta a integración de Kafka fai que todas as nosas probas unitarias sexan asíncronas. Resolvemos este problema escribindo os nosos propios métodos de utilidade usando Embedded Kafka Broker. Isto non elimina a necesidade de escribir probas unitarias para métodos individuais, pero preferimos probar casos complexos usando Kafka.

Prestouse moita atención ao rastrexo dos rexistros para que o seu TraceId non se perda cando se produzan excepcións durante o funcionamento dos servizos ou cando se traballa co lote Kafka. E se non houbo problemas especiais co primeiro, entón no segundo caso vémonos obrigados a rexistrar todos os TraceIds cos que chegou o lote e seleccionar un para seguir rastrexando. Despois, ao buscar polo TraceId orixinal, o usuario descubrirá facilmente con cal continuou o rastrexo.

Tarefa 3. A necesidade de almacenar unha gran cantidade de datos: Máis de mil millóns de etiquetas ao ano só para o tabaco chegan a X1. Requiren un acceso rápido e constante. En total, o sistema debe procesar uns 5 millóns de rexistros do historial de movementos destas mercadorías etiquetadas.

Para resolver o terceiro problema, escolleuse a base de datos NoSQL MongoDB. Construímos un fragmento de 5 nodos e cada nodo ten un conxunto de réplicas de 3 servidores. Isto permítelle escalar o sistema horizontalmente, engadindo novos servidores ao clúster e garantir a súa tolerancia a fallos. Aquí atopamos outro problema: garantir a transaccionalidade no clúster mongo, tendo en conta o uso de microservizos escalables horizontalmente. Por exemplo, unha das tarefas do noso sistema é identificar os intentos de revender produtos cos mesmos códigos de etiquetaxe. Aquí aparecen superposicións con escaneos erróneos ou operacións erróneas dos caixeiros. Descubrimos que estes duplicados poden producirse tanto dentro dun lote de Kafka que se está procesando como dentro de dous lotes que se procesan en paralelo. Así, a comprobación de duplicados consultando a base de datos non deu nada. Para cada microservizo, resolvemos o problema por separado en función da lóxica empresarial deste servizo. Por exemplo, para as comprobacións, engadimos unha comprobación dentro do lote e un procesamento separado para a aparición de duplicados ao inserir.

Para garantir que o traballo dos usuarios co historial de operacións non afecte de ningún xeito o máis importante: o funcionamento dos nosos procesos comerciais, separamos todos os datos históricos nun servizo separado cunha base de datos separada, que tamén recibe información a través de Kafka. . Deste xeito, os usuarios traballan cun servizo illado sen afectar aos servizos que procesan datos para operacións en curso.

Tarefa 4: Reprocesamento e seguimento da fila:

Nos sistemas distribuídos, inevitablemente xorden problemas e erros na dispoñibilidade de bases de datos, filas e fontes de datos externas. No caso de Marcus, a fonte destes erros é a integración con sistemas externos. Era necesario atopar unha solución que permitise solicitudes repetidas de respostas erróneas cun tempo de espera especificado, pero que ao mesmo tempo non deixara de procesar as solicitudes exitosas na cola principal. Para este fin, escolleuse o denominado concepto de "reintento baseado en temas". Para cada tema principal créanse un ou varios temas de reintento aos que se envían mensaxes erróneas e, ao mesmo tempo, elimínase o atraso no procesamento das mensaxes do tema principal. esquema de interacción -

"Camiñando cos meus zapatos" - espera, están marcados?

Para implementar tal esquema, necesitabamos o seguinte: integrar esta solución con Spring e evitar a duplicación de código. Mentres navegabamos pola web, atopamos unha solución similar baseada en Spring BeanPostProccessor, pero pareceunos innecesariamente engorroso. O noso equipo fixo unha solución máis sinxela que nos permite integrarnos no ciclo Spring para crear consumidores e engadir, ademais, Retry Consumers. Ofrecémoslle un prototipo da nosa solución ao equipo de Spring, podedes velo aquí. O número de Consumidores de reintentos e o número de intentos para cada consumidor configúrase mediante parámetros, dependendo das necesidades do proceso empresarial, e para que todo funcione, só queda engadir a anotación org.springframework.kafka.annotation.KafkaListener , que é familiar para todos os desenvolvedores de Spring.

Se a mensaxe non se puido procesar despois de todos os intentos de reintento, vai a DLT (tema de letra morta) mediante Spring DeadLetterPublishingRecoverer. A petición de asistencia, ampliamos esta funcionalidade e creamos un servizo separado que che permite ver as mensaxes incluídas en DLT, stackTrace, traceId e outra información útil sobre elas. Ademais, engadíronse vixilancia e alertas a todos os temas DLT, e agora, de feito, a aparición dunha mensaxe nun tema DLT é un motivo para analizar e corrixir un defecto. Isto é moi conveniente: polo nome do tema, entendemos inmediatamente en que etapa do proceso xurdiu o problema, o que acelera significativamente a busca da súa causa raíz.

"Camiñando cos meus zapatos" - espera, están marcados?

Máis recentemente, implementamos unha interface que nos permite reenviar mensaxes utilizando o noso soporte despois de eliminar as súas causas (por exemplo, restaurar a funcionalidade do sistema externo) e, por suposto, establecer o defecto correspondente para a súa análise. Aquí é onde os nosos autotemas son útiles: para non reiniciar unha longa cadea de procesamento, pode reiniciala dende o paso desexado.

"Camiñando cos meus zapatos" - espera, están marcados?

Operación da plataforma

A plataforma xa está en funcionamento produtivo, cada día realizamos entregas e envíos, conectamos novos centros de distribución e tendas. Como parte do piloto, o sistema traballa cos grupos de produtos "Tabaco" e "Zapatos".

Todo o noso equipo participa na realización de pilotos, analiza os problemas emerxentes e fai suxestións para mellorar o noso produto, desde mellorar os rexistros ata cambiar os procesos.

Para non repetir os nosos erros, todos os casos atopados durante o piloto reflíctense en probas automatizadas. A presenza dun gran número de probas automáticas e probas unitarias permítelle realizar probas de regresión e instalar un hotfix literalmente nunhas poucas horas.

Agora seguimos desenvolvendo e mellorando a nosa plataforma e afrontando constantemente novos retos. Se estás interesado, falaremos das nosas solucións nos seguintes artigos.

Fonte: www.habr.com

Engadir un comentario