optimización de un sistema de alta carga / Sudo Null IT News

¡Hola! Mi nombre es Innokenty Kornilov, soy un ingeniero de desarrollo líder en Bercut, donde trabajo desde 2013.

Desarrollo y soporte el sistema “Autoassembly”, que data del año 2007. Este es un sistema de gestión de configuración que automatiza los procesos de creación, control de versiones y lanzamiento de versiones; una herramienta clave que garantiza la coherencia en el desarrollo y lanzamiento de software en toda nuestra empresa. Gracias a Autoassembly, podemos gestionar el proceso de montaje de componentes y sistemas, mantener la versión y el estado de preparación de los productos y garantizar su correcta entrega a los clientes.

El artículo está dedicado a la historia de la superación de algunas dificultades técnicas que surgieron en las distintas etapas del proyecto y a una descripción de los puntos clave que determinaron nuestro enfoque para trabajar en el sistema.

Actué en diferentes roles en el proyecto, desde analista y arquitecto hasta especialista en desarrollo y pruebas, líder de equipo (también participo en proyectos comerciales: Motor de reglas de negocio, Portabilidad del número móvil, Gestión de perfiles de servicio etc.).

Características clave del sistema Autoassembly

El “autoensamblaje” garantiza el proceso unificado de desarrollo y lanzamiento de software adoptado por Bercut, proporcionando las siguientes capacidades:

  • Asegura la calidad y eficiencia requeridas en el desarrollo, implementación y mantenimiento de nuestras soluciones.

  • Identifica de forma única todos los artefactos utilizados o creados durante el proyecto.

  • Garantiza el lanzamiento de soluciones mantenibles sin nuestra participación.

  • Identifica y monitorea el estado de los artefactos de diseño en cualquier momento dado, incluida su idoneidad y grado de finalización.

  • Gestiona el procedimiento de montaje de componentes y sistemas para garantizar la reproducibilidad, la eficiencia y el control necesario.

  • Gestiona los cambios, asegurando la integridad y trazabilidad necesarias para las configuraciones de los artefactos de diseño en todas las etapas de desarrollo, entrega y mantenimiento.

    Si especifica el identificador de versión exacto del sistema/componente, siempre podrá obtener instrucciones exactas para ensamblar esta versión y utilizar estas instrucciones: 1. Cree una copia idéntica desde cero a partir de los códigos fuente en un equipo “limpio” y obtenga un conjunto completo. de documentación operativa y técnica precisa y actualizada para esta versión; 2. Reproducir cualquier cambio en cualquiera de los artefactos del proyecto de una versión a otra, incluidos los cambios en todos los artefactos incluidos en éste.

  • Proporciona un flujo de trabajo de desarrollo unificado y control de versiones unificado de artefactos.

    El control de versiones garantizado por el proceso elimina la posibilidad de que surjan problemas, por ejemplo, asociados con la sobrescritura de etiquetas en Git. El “autoensamblaje” controla y apoya este proceso. Bercut tiene una estricta política de compatibilidad con versiones anteriores de los componentes desarrollados. Los cambios de versión dentro de los primeros dos dígitos garantizan a los usuarios que el componente seguirá siendo funcional, no requerirá pruebas de regresión y es solo una corrección de errores.

  • Garantiza la coherencia en las configuraciones de artefactos. No es necesario crear sus propios scripts de compilación, ya que utilizamos compiladores y motores de compilación centralizados. No existe un “zoológico” de diferentes enfoques para el montaje en diferentes equipos. Un proceso unificado de desarrollo y montaje elimina situaciones en las que algún especialista se ha ido y nadie sabe cómo montar un componente. El montaje está siempre garantizado.

  • Describe declarativamente la configuración de componentes y sistemas.

    Disponemos de muchos tipos de componentes que se ensamblan para varios sistemas operativos y utilizando varios compiladores, desde plataformas de hardware específicas hasta NodeJS. El “ensamblaje automático” proporciona una configuración declarativa única, lo que simplifica enormemente el proceso de introducción de nuevos empleados y la transición entre proyectos.

  • Recoge nuestras soluciones para diversas plataformas y compiladores.

Plataformas:

WIN32, WIN64, SOLARIS 9, SOLARIS 10, SOLARIS 10×64, LINUX POWER PC, LINUX SUSE, JAVA, MULTIPLATAFORMA, LINUX SUSE x32, RHEL 5.5, RHEL 5.5 x32, RHEL 7, CENTOS 7, ALMA 9

Compiladores:

DELPHI 6.0, DELPHI 10.0, DELPHI 10.3, DELPHI 11.0, DELPHI 11.1, MSVC 6.0, MSVC 8.0, MSVC 17.0, GCC 3.0, GCC 3.2, GCC 3.3, JDK 14, JDK 15, GCC 4.1, SUNC 5.8, LDC 2.0, AB 1.4 , TAB 1.6, TAB 2.0, TAB 2.1, JDK 16, JDK 17, JDK 18, JDK 19, JDK 130, JCDK 2.1, LIFERAY 5.1, NETBEANS 6.5, NETBEANS 8.2, OPEN ESB STUDIO 3.1, GCC 4.7, GCC 4.8.3, WSDL 3.1, WSDL 3.2, WSDL 3.3, EXTENSIÓN*.

*EXTENSION es un punto de extensión que le permite crear artefactos utilizando constructores, compiladores y herramientas de línea de comandos externos como Gradle, Maven, Angular CLI, npm, Sencha Cmd y otros.

  • Proporciona reutilización de código. Montamos nuestros productos como kits de construcción, sistemas de formación a partir de componentes y cada artefacto puede tener su propio ciclo de vida. Utilizamos un único registro y repositorio de artefactos. Al desarrollar nuevos componentes y sistemas, utilizamos artefactos creados previamente.

  • Históricamente, AutoBuild ha podido interactuar simultáneamente con varios sistemas de control de versiones (StarTeam, SVN, Bitbucket, GitLab, etc.).

  • Automatiza tareas rutinarias: gestionar sucursales en el sistema de control de versiones (VCS) al lanzar nuevas versiones de artefactos, crear etiquetas para lanzamientos y muchas otras operaciones.

  • Proporciona seguimiento del uso de componentes. Podemos claramente realice un seguimiento de en qué artefactos se utiliza cada componente, así como en qué sistemas está incluido. Esto es especialmente importante si se detecta un error en un componente, porque… es posible determinar exactamente en qué sistemas está integrado. Esta información le permite determinar qué sistemas requieren una reedición o actualización para el cliente.

  • El soporte para el ensamblaje local brinda a los desarrolladores la oportunidad de ensamblar de forma independiente un componente o sistema en sus dispositivos, garantizando un resultado idéntico al del ensamblaje centralizado a través del portal AutoBuilds.

  • El sistema se puede utilizar para realizar procedimiento de depósito en garantíapermitiendo, en función de las versiones enviadas, crear un repositorio con códigos fuente, a partir del cual se pueden crear versiones idénticas en el sitio del cliente.

  • Le permite realizar cambios en un artefacto recopilado hace varios años, reconstruirlo y obtener una copia exacta con las correcciones realizadas.

    Incluso si los miembros del equipo se van, cualquier otro desarrollador puede conectarse fácilmente, realizar los cambios necesarios, ensamblar el artefacto y obtener el mismo producto que antes, solo teniendo en cuenta los cambios realizados.

  • Recopila métricas y analiza la calidad del código.

  • Proporciona el ciclo de vida de desarrollo, prelanzamiento y lanzamiento.

    En la etapa de desarrollo, el artefacto se transfiere al estado de prelanzamiento, que es una sección congelada que no se puede volver a ensamblar. Un artefacto en estado previo al lanzamiento se envía para su prueba y, si las pruebas son exitosas, se lanza el producto.

  • Proporciona mecanismos para liberar parches.

    Le permite lanzar un parche menor a una versión del sistema ya publicada.

Descripción del sistema

La “compilación automática” consta del servidor principal y los agentes de compilación. Cada sistema operativo cuenta con un agente de compilación independiente.

Inicialmente, en el servidor principal, además del núcleo del sistema y el portal, había una base de datos PostgreSQL y un agente de compilación.

Hay varios tipos de artefactos en Auto Assembly, como componentes y sistemas. Como escribí anteriormente, nuestros productos y soluciones tienen una estructura de componentes. No escribimos cada nuevo producto desde cero, sino que desarrollamos componentes individuales responsables de una funcionalidad específica. Podemos reutilizar componentes previamente desarrollados.

Un sistema es un producto final que consta de componentes y puede incluir otros sistemas. La versión de lanzamiento del sistema se envía al cliente.

El “autoensamblaje” es también un proceso unificado para desarrollar y lanzar software a nivel empresarial. Cualquier artefacto en un sistema de gestión de configuración tiene su propia versión única. Los artefactos incluyen versiones del sistema y de los componentes, compilaciones, correcciones urgentes, etc. Cada compilación tiene su propio estado de preparación. El “Autoensamblaje” elimina la situación en la que el cliente puede recibir un artefacto con la misma versión, pero con diferentes versiones del código fuente.

Los componentes y sistemas se configuran según un principio único, independientemente de qué sistemas operativos, para qué compiladores esté ensamblado el artefacto o en qué idioma esté escrito. El desarrollador simplemente especifica cómo se debe ensamblar este artefacto y el “Autoensamblaje” hace el resto.

Para crear un nuevo componente en AutoBuild, el desarrollador va al portal, crea un componente, especifica la versión y el nombre del componente, especifica los compiladores y sistemas operativos, los componentes dependientes que son necesarios para construir el nuevo artefacto. Al crear un componente, AutoBuild genera automáticamente una ruta en el sistema de control de versiones en la que se almacenará el código fuente. Los sistemas se crean utilizando el mismo principio.

Cuando un desarrollador envía su componente para su ensamblaje (a través de la GUI, IDE o mediante confirmación), la tarea termina en la cola general de “Construcción automática”. Además del componente que se está creando, los componentes dependientes que utilizan este componente también se ponen en cola si no se encuentran en estado de lanzamiento previo o lanzamiento.

La cola muestra las tareas de compilación enviadas por todos los desarrolladores e informa sobre el tiempo previsto de finalización de las compilaciones.

Una vez ensamblado un componente, su ensamblaje, que tiene su propia versión única, se carga en el repositorio interno “Autoassemblies”. Luego, el componente se puede utilizar para ensamblar otros componentes o sistemas.

Optimización de bases de datos: indexación y división en máquinas separadas

Con el aumento en el número de artefactos y el número de tareas de montaje, el proceso comenzó a ralentizarse.

Para aumentar el rendimiento y reducir la carga en el servidor central, decidimos:

  • mover el agente de compilación a una máquina separada de un servidor central;

  • mover la base de datos a una máquina separada;

  • virtualice algunas máquinas físicas y agrégueles recursos.

También analizamos los índices existentes, identificando aquellos que no se utilizaron en las consultas o que se utilizaron con muy poca frecuencia. Estos índices se eliminaron para reducir la carga en las operaciones de actualización de tablas porque cada índice requiere volver a indexarse ​​cuando se agregan, actualizan o eliminan filas, lo que hace que estas operaciones se vuelvan más lentas.

Luego, basándose en el análisis estadístico de las consultas más frecuentes y “pesadas”, creamos nuevos índices. El punto clave fue trabajar con índices de árbol B, que proporcionan una búsqueda eficiente de un rango de valores y reducen significativamente el tiempo de búsqueda al reducir la cantidad de páginas que deben leerse. El objetivo era reducir el número de escaneos secuenciales de tablas, reemplazándolos con escaneos de índice. Paralelamente al trabajo sobre índices, revisamos y optimizamos consultas SQL; Algunas consultas fueron reescritas. Especialmente en esa parte de la lógica donde hubo múltiples llamadas a la base de datos. Se han reemplazado pequeñas consultas múltiples por consultas que devuelven todos los datos necesarios a la vez.

Todas estas medidas permitieron duplicar la velocidad de montaje de sistemas y componentes.

Escalado mediante agrupación de agentes y compilaciones paralelas

En la siguiente etapa, Avtosborka continuó ampliando su funcionalidad:

  • Junto con SVNintegración con Bitbucket;

  • Ha aparecido la integración con Jira;

  • Se agregó la formación de un historial de compilación que, independientemente del VCS utilizado, mostraba los cambios de código dentro de cada compilación y cada versión.

  • La lista de sistemas operativos compatibles ha aumentado. En ese momento, “Autoassembly” podía recopilar artefactos para diferentes versiones y diferentes tamaños de bits de sistemas operativos como Solaris SPARC, RHEL, Windows, LinuxPWPC, LinuxSUSE, CentOS, etc. En total había más de 12 opciones para combinaciones de sistema operativo y profundidad de bits. Además, “Autoassembly” admitía más de 30 versiones de varios compiladores.

La cantidad de productos producidos ha aumentado significativamente y, como resultado, la carga en el sistema.

El montaje de cada componente es una tarea compleja que implica no uno, sino varios procesos de montaje. Por ejemplo, para algunos tipos de componentes, para cada sistema operativo y compilador especificado en la configuración, se producen dos tipos de compilaciones: una para depurar y la segunda para la principal. Si se supone que el artefacto se usará en cinco sistemas operativos diferentes y cada uno requiere dos versiones para dos compiladores, al final, teniendo en cuenta la presencia de una versión de depuración, obtenemos 20 archivos binarios creados dentro de un ensamblaje.

En este caso, el ensamblaje de un componente también implica el ensamblaje de componentes que dependen de él, si es necesario volver a ensamblarlos y se encuentran en estado de Desarrollo. Inicialmente, se introdujo la funcionalidad para reconstruir componentes dependientes para aplicaciones C++. La preparación de un único componente puede dar lugar a cientos de compilaciones para mantener todos los artefactos asociados coherentes y actualizados.

Durante el análisis se identificaron dos problemas importantes, cuya solución permitió acelerar todo el proceso varias veces. El primer cuello de botella fue el ensamblaje secuencial del artefacto para varios sistemas operativos, cuando el ensamblaje para el siguiente sistema operativo comenzó solo después de completar el ensamblaje del anterior. Como solución, se implementó una funcionalidad que paralelizó este proceso, lo que permitió acelerar en más de 4 veces el ensamblaje de un artefacto ensamblado para diferentes SO.

La segunda pregunta estaba relacionada con el montaje simultáneo de varios artefactos para un sistema operativo.

Para compilar para un sistema operativo, se asignó un agente de compilación en el sistema. A medida que crecía la carga de trabajo, un agente se volvió insuficiente. Paralelizar el ensamblaje en un host tampoco fue una solución completa, ya que al ensamblar 3-4 componentes simultáneamente, el tiempo de ensamblaje de un componente aumentaba varias veces. Como solución, se agregó compatibilidad con el grupo de agentes para cada sistema operativo. Esta mejora hizo posible recopilar simultáneamente varios artefactos bajo el mismo sistema operativo en diferentes agentes.

También se agregó un mecanismo de equilibrio de carga que proporcionaba el agente menos cargado del grupo. El ensamblaje de un sistema operativo comenzó a realizarse en diferentes hosts, en paralelo, en 10 subprocesos. Esto acelera el procesamiento de la cola de compilación más de 10 veces.

Nuevas tareas, integración con GitLab y optimización de procesos.

Era necesario introducir nuevos requisitos de producción. Se agregó integración con GitLab y el desarrollo principal pasó a utilizar este sistema de control de versiones. Paralelamente, algunos sistemas y componentes permanecieron en SVN y Bitbucket. Se llevaron a cabo migraciones a gran escala de proyectos desarrollados de Bitbucket y SVN a GitLab. Se agregó funcionalidad para integración continua y entrega de CI/CD, gracias a la cual cualquier impulso en GitLab podría iniciar la construcción de los componentes correspondientes, sus dependencias y los sistemas en los que se incluyen estos componentes. Avtosborka ahora tiene una funcionalidad para enviar lanzamientos automáticamente a los clientes. Para interactuar con sistemas externos, se agregó el intermediario de mensajes RabbitMQ y se organizó un análisis automático de la calidad de los códigos fuente de los componentes ensamblados. Desarrollo adicional e integración con ENTENDER LA IDEAque le permite administrar el estado y el ensamblaje de características y artefactos directamente desde el IDE.

El número de conexiones entre artefactos ha aumentado. La cantidad de artefactos en el sistema ha aumentado. Después de analizar la lógica operativa, encontramos un nuevo punto de optimización. Cuando se ensambla un artefacto para varias plataformas, se forma un árbol de dependencia de este artefacto para el ensamblaje. Y dado que puede haber muchas dependencias, crear un árbol de este tipo puede ser una operación muy costosa.

Hemos agregado un caché en memoria al árbol de dependencia. Durante el proceso de ensamblaje, el árbol de dependencia se formó una vez y luego se reutilizó al ensamblar para varios sistemas operativos. La presencia de tal árbol nos permitió acelerar el montaje decenas de veces.

Anteriormente, los agentes de compilación utilizaban compiladores ubicados en el servidor principal. Para mejorar el rendimiento, los compiladores se colocaron directamente en cada agente de compilación. Además, para garantizar el estado actual de los compiladores, se desarrolló un programa especial para sincronizarlos. Los agentes también tienen discos RAM, que son secciones de RAM que se utilizan como alternativa ultrarrápida a un disco duro. Se les transfirieron procesos que requieren un acceso frecuente e intensivo al disco, lo que aceleró aún más el proceso de compilación.

Conclusión

Por el momento, “Autoassembly” es un sistema muy cargado que garantiza el trabajo simultáneo de cientos de desarrolladores que recopilan sus artefactos todos los días. Por ejemplo, durante el último mes, se entregaron más de 10.000 tareas a la asamblea. El repositorio de AutoAssembly almacena actualmente más de 1.000.000 de artefactos y este número sigue creciendo.

Hay nuevos desafíos por delante. Hay varias áreas clave de atención en el futuro cercano:

  1. Optimización de consultas a bases de datos y mejora de índices. Continuaremos mejorando el rendimiento de la base de datos para acelerar el procesamiento de datos y mejorar la velocidad general del sistema.

  2. Implementación de fragmentación de bases de datos. Esto ayudará a distribuir la carga de manera más eficiente, evitará cuellos de botella cuando crezcan los volúmenes de datos y aumentará la tolerancia a fallas del sistema.

  3. Usando Redis para almacenamiento en caché. Esto reducirá el tiempo de acceso a la información clave y reducirá la carga en la base de datos, lo que acelerará el proceso de ensamblaje y procesamiento de artefactos.

  4. Pool dinámico de agentes de compilación con contenedorización usando Docker y Kubernetes. Esto le permitirá aumentar dinámicamente la cantidad de agentes dependiendo de la carga actual en el sistema, brindando flexibilidad y escalabilidad del grupo para manejar tareas pico.

  5. Haga la transición a una arquitectura basada en eventos con RabbitMQ. Permitirá que el sistema responda a eventos en tiempo real, mejorará el procesamiento paralelo de tareas y aumentará la flexibilidad de interacción entre componentes, lo que proporcionará una mejor escalabilidad y resistencia a cargas elevadas.

  6. Integración con los servicios domésticos. Planeamos ampliar la integración con los servicios nacionales al incluir sistemas de gestión de proyectos, repositorios, programadores de tareas, etc.

    El sistema continuará desarrollándose y proporcionando configuración y gestión de compilación en Bercut.

Publicaciones Similares

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *