Меня зовут Максим Старков, я работаю в команде управления системами 1С компании «ДНС Ритейл». Наша команда занимается вопросами, связанными с эксплуатацией систем, реализованных на платформе «1С:Предприятие».
Я хочу рассказать о том, как работает 1С размером в 13 ТБ в условиях непрерывной разработки, а также поделиться опытом эксплуатации таких систем.
Задачи команды эксплуатации
Итак, перед командой эксплуатации стоит множество задач. Но мы выделяем три основных:
- Первая – это обеспечение непрерывного и быстрого обмена данными между всеми связанными системами, которые покрывают всю территорию Российской Федерации.
- Вторая – обеспечение ежедневного обновления конфигурации в рамках отведенного технологического окна
- И третья – обеспечение мониторинга работы систем для раннего выявления проблем и их устранения.
Итак, давайте я по каждой задаче поделюсь некоторым опытом.
Архитектура системы базового обмена данными
Большой бизнес всегда предполагает большой объем данных. Эти данные нужно собирать, сохранять, обрабатывать, а также обмениваться ими между всеми связанными системами.
- Оценить объем данных в компании ДНС достаточно сложно. Он зависит от многих факторов. Но в среднем можно сказать, что за одну итерацию обмена между двумя узлами уходит около 50 Мб данных.
- Обмен выполняется каждые 15 минут. В итоге за один день между двумя узлами проходят миллионы объектов.
- Из всех систем можно выделить основную – мы называем ее центральной или управленческой базой данных. Она состоит из головного узла и 9 подчиненных территориально распределенных узлов. Это классический вариант распределенной базы данных. На данный момент размер основного узла центральной базы составляет 13Тб. Региональные узлы имеют размеры от 1 до 2 Тб данных.
- Кроме этого, у нас также есть и другие системы. Это – склад, сайт, система продаж и бухгалтерия. Со всеми этими системами нам нужно обмениваться.
Для производительной работы обменов мы используем свои подходы к регистрации изменений объектов, формированию и выгрузке пакетов.
Мы используем в основном типовые возможности платформы. Для регистрации изменений мы применяем несколько планов обменов и свой специальный регистр сведений, структура которого, как видно, почти полностью повторяет структуру таблицы регистрации изменений.
Если с планами обмена все понятно, то зачем нам понадобился дополнительный регистр сведений? Он нам нужен для того, чтобы в нем регистрировать изменения тех объектов, которые при выгрузке и загрузке должны с собой забирать связанные данные, чтобы в момент загрузки в единой транзакции загрузить не только сами данные, но и все, что с ними связано. Таким образом, мы обеспечиваем целостность загружаемых данных в базах источниках.
Чтобы увеличить параллельность работы при выгрузке и формировании пакетов, мы используем прямые запросы в базу данных:
- первое, что мы делаем, – это устанавливаем с помощью прямого запроса номера сообщений для пакетов (я думаю, все знакомы с квитированием обычных обменов);
- и также прямым запросом очищаем таблицы изменений – но в основном это делаем только с нашим регистром сведений.
Таким образом, мы довольно быстро умеем выгружать данные и при этом оказываем минимальное воздействие на возможность параллельной работы других сеансов.
Далее – формируем пакет обмена:
- При записи информации в пакет обмена мы используем свои XML-узлы и атрибуты XML-узлов. Они понадобятся нам в дальнейшем, когда мы эти данные будем считывать.
- Чтение данных в базах-приемниках мы выполняем в параллельном режиме.
- Специальные XML-узлы и атрибуты предназначены для того, чтобы наши алгоритмы параллельного чтения распределяли порции из пакетов и загружали их параллельно. На рисунке можно увидеть, что у нас в каждом XML-узле есть атрибут Order, и при считывании в базе-источнике все данные, которые в нем находятся, распределяются между пулом потоков, который реализован на основе фоновых заданий. Здесь тоже ничего удивительного нет.
Таким образом, мы умеем быстро выгружать и загружать данные, поддерживая продолжительность цикла обмена не более 15 минут. На самом деле, получается значительно быстрее.
Apache Kafka для обмена данными по изменениям цен
Однако мы столкнулись с проблемой массового изменения цен. У нас в компании очень много номенклатуры, и цены могут меняться почти на всю номенклатуру. Эти изменения нужно синхронизировать между всеми связанными системами.
Изначально все эти данные передавались через систему базового обмена. Но она не могла справиться с такой нагрузкой и замедляла обмен другими объектами.
Было принято решение вынести этот контур обмена в отдельную систему, и в качестве транспорта для этой системы мы решили использовать брокер сообщений Apache Kafka.
Совместно с командой администрирования мы разработали следующую архитектуру нашего зоопарка Kafka. Вкратце ее можно описать так:
- у нас есть три кластера Apache Kafka, распределенных по разным регионам всей России;
- в каждом кластере – по три брокера;
- в каждом брокере есть три темы;
- и в каждой теме – по 10 разделов (партиций);
- данные в кластере синхронизируются по брокерам с помощью внутренних механизмов Apache Kafka (обычно это репликация, а у нас – тройная репликация).
- Также мы синхронизируем данные между кластерами. Из коробки Kafka этого делать не умеет. Но есть прекрасная утилита MirrorMaker, с помощью которой у нас, по сути, три наших кластера хранят в себе одни и те же данные, и географически распределены по всей России.
Что мы делаем дальше?
- Когда происходит изменение цен, мы записываем эти данные в соответствующую тему. Кроме этого, мы формируем хэш для записи. То есть указываем ключ, который определяется по наборам характеристик номенклатуры. Таким образом, каждая номенклатура с определенным набором характеристик всегда попадает в одну и ту же партицию (или в раздел). Я уже говорил, у нас их 10, и это – жесткая настройка. Если мы изменим количество разделов, у нас, конечно, все «уедет». Или придется как-то останавливать обмен, и все это приводить в порядок.
- Для чего нам нужно соблюдать соответствие номенклатурных позиций определенным партициям? Это нужно, потому что Kafka не гарантирует порядок записи сообщений в одной теме. Гарантия записи сообщений есть только в том случае, когда мы пишем в один и тот же раздел. Таким образом, мы храним в Kafka историю цен. Там есть небольшой промежуток времени, за который хранится вся история цен.
- Дальше, для работы с Apache Kafka и 1С мы решили использовать Rest Proxy интерфейс от разработчиков Kafka (фирмы Confluent). Он бесплатен, любой может его поднять. И в принципе можно работать с Apache Kafka из 1С без внешних компонент, используя стандартное HTTP-соединение. Возможно, это работает не так быстро, как компоненты от известных на Инфостарте людей, но очень хорошо работает.
Наша архитектура позволила нам создать отказоустойчивый кластер с тройной репликацией, а также масштабировать чтение.
Каждый кластер хранит в себе данные цен всех других регионов. Поэтому чтение цен других регионов выполняется очень быстро:
- с помощью Apache Kafka мы получили некое централизованное хранилище цен, отдельную систему;
- данные по ценам больше не нагружают основной обмен – он работает, как и раньше;
- значительно сократилось общее время от момента изменения цены до синхронизации этих данных между всеми системами. Также получили большой плюс, что к нашему хранилищу цен на Kafka могут подключаться и другие системы – это система продаж, сайт и вообще, кто угодно.
В итоге мы можем обеспечить довольно быстрый обмен данными между всеми нашими системами и укладываться в отведенное для этого время.
Автоматизация обновления конфигураций
Следующая задача нашей группы эксплуатации – это автоматизация обновления конфигураций.
- У нас много программистов, они выполняют очень много помещений (коммитов) в хранилище – порядка 30 в день, иногда даже значительно больше.
- И бизнес говорит нам, что мы должны обновлять конфигурацию баз данных каждый будний день.
- Но с этим есть одна проблема – время для обновления (допустимое технологическое окно) – с 6 до 7 утра по времени Владивостока.
Чтобы избежать ручной работы команды эксплуатации мы решили создать свою систему автоматического обновления нашей распределенной конфигурации.
Архитектурно, система автоматического обновления имеет:
- служебную конфигурацию на платформе 1С:Предприятие
- и специальное приложение, написанное на C#, которое установлено в качестве службы на всех рабочих серверах кластеров 1С, которые у нас есть.
На скриншотах вы можете видеть функциональность служебной конфигурации.
Также в течение рабочего дня мы производим постоянный анализ помещения изменений в хранилище. Мы пытаемся найти те реструктуризации, которые могут привести к длительному обновлению конфигурации и выходу за рамки технологического окна.
В принципе, это можно сделать с помощью технологического журнала и его определенных настроек, которые есть на партнерском форуме. У кого нет доступа к партнерскому форуму, эти настройки можно найти на Инфостарте.
В технологическом журнале мы получаем событие System, в котором выводится вся нужная информация – какие объекты метаданных будут реструктуризированы, какая это будет реструктуризация – полная или не полная. Кроме этого, у нас есть накопленная статистика по времени реструктуризации тех или иных таблиц баз данных.
В итоге в течение дня после каждого коммита из основного хранилища выгружается cf-ник. Он накатывается на копию базы данных, для которой настроен вывод такого технологического журнала. И происходит обновление конфигурации. Дальше наши внутренние средства анализируют эти данные, получают статистику по времени реструктуризации, и мы в прямом эфире видим, кто из разработчиков какие поместил изменения, и какие реструктуризации нам предстоит произвести.
Таким образом, мы можем заранее отловить тот момент, когда какой-нибудь разработчик решит добавить реквизит в регистр сведений, в котором находятся несколько миллиардов записей.
Вернусь к автоматизации обновления. Все довольно просто. Мы не используем современные технологии, в том числе другие движки, которые умеют читать язык 1С. Так повелось исторически, но мы довольны.
У нас запуск автоматического обновления происходит, когда в пакете обмена есть данные конфигурации.
В этот момент алгоритм конфигурации обращается к специальной службе, установленной на всех рабочих серверах кластера, посылает ей определенный набор команд, и служба начинает выполнять все необходимые действия для установки обновлений:
- она закрывает соединения с базой данных;
- в случае необходимости удаляет сеансы, которые «зависли»;
- при необходимости может даже рестартануть службу (бывает такое, что сеансы могут остаться – например, в случае какого-нибудь длительного отката транзакции, когда сеанса уже нет, соединение с базой данных будет держаться, и соединение в кластере тоже будет жить).
Такой механизм позволяет в течение часа (в период технологического окна) обновить нашу конфигурацию во всех узлах – центральный узел и все 9 узлов, от Дальнего Востока до Калининграда.
В итоге мы умеем контролировать процедуру автоматического обновления.
Служебная конфигурация общается со службами, которые установлены на всех рабочих серверах, и позволяет нам контролировать все этапы, по которым проходит автоматическое обновление. В случае возникновения каких-то проблем происходит оповещение в мессенджер, и здесь уже приходится действовать вручную, смотреть, что случилось. Но такое бывает редко, в основном все проходит автоматически в то время, когда мы спим.
Мониторинг систем
Дальше – основная наша третья задача – это мониторинг работы систем. В основном, это, конечно, системы на платформе 1С:Предприятие, потому что другими системами занимаются другие люди из команды системных администраторов.
Для мониторинга мы используем несколько подходов:
- во-первых, это сбор логов работы приложений;
- второе – это сбор показателей производительности оборудования и серверов;
- и третье – это сбор собственных метрик.
Сбор логов приложений 1С
Мониторинг работы приложений у нас реализован следующим образом:
- Наш основной рабочий инструмент – это, конечно, технологический журнал платформы 1С. Мы его очень активно применяем.
- На каждом рабочем сервере у нас настроен вывод всех важных событий технологического журнала, а также собираются все события длительностью более 1 секунды. Наш технологический журнал получается довольно массивным, но мы не храним большой период, нам важно оперативно решать проблемы и иметь небольшую историю – хотя бы месяц.
- Для обработки данных технологического журнала мы используем стек технологий EBK (Elasticsearch, Beats и Kibana).
- Большая часть анализа выполняется автоматически. У нас есть список определенных запросов в Elasticsearch, результаты которых говорят нам о том, что что-то пошло не так: либо появились какие-то управляемые блокировки, либо runtime-ошибки, либо непонятные перезапуски рабочих процессов и т.д.
Поскольку технологический журнал – это единственное, что нам дает платформа для того, чтобы что-то понять, то для анализа технологического журнала мы используем инструменты EBK.
Всю работу можно описать следующим образом – с помощью сборщика логов Filebeat мы отправляем данные с каждого рабочего сервера в Elastic.
На слайде показана обычная настройка для Filebeat, чтобы он научился собирать логи технологического журнала – указаны пути к каталогам, паттерн для поиска событий в ТЖ.
В том числе мы добавляем свои поля – log_type, log_timezone (так как у нас распределенная система, нам обязательно нужно указывать временную зону, иначе у нас появляется неразбериха).
Обработкой поступающих данных занимается сам Elastic. В нем есть прекрасная возможность Ingest Node – она по умолчанию уже задействована и работает. Если Elastic состоит из нескольких служб, то Ingest Node можно назначить на любой из серверов, из которых состоит кластер. С помощью настроенного Pipeline Ingest Node умеет парсить данные техжурнала.
С помощью pipeline мы разбираем запись лога технологического журнала на определенные фрагменты – выявляем оттуда:
- длительность;
- имя события;
- номер сеанса;
- контекст;
- description в Exception и много других параметров.
В принципе вы можете найти такой pipeline в интернете, чтобы ничего не изобретать – он там есть. Там только одна хитрость – Filebeat и Elasticsearch будут по умолчанию записывать данные в техжурнал с тем временем, с которым Filebeat их отправил. Но нам нужно точное время из записи самого техжурнала, а для этого нужно поработать над этим pipeline, чтобы вырезать данные, склеить их и записать настоящее время.
В итоге все это выглядит вот так – мы анализируем информацию с помощью Kibana (визуализатор для Elasticsearch). У нас в Kibana настроено много каких-то своих отборов, агрегаций. В том числе есть различные дашборды.
Кроме этого, иногда возникает необходимость собрать более подробные данные технологического журнала. Например, мы исследуем проблемы с производительностью какого-то механизма, какого-то фонового задания, или какой-то пользователь вдруг начал жаловаться на производительность. В этом случае мы формируем в файле настроек технологического журнала отдельный узел, где указываем отдельное местонахождение для вывода файлов технологического журнала в отдельный каталог. И Filebeat, когда производит чтение из этого каталога, шлет эти данные уже не в основные индексы технологического журнала, а в специальный индекс трассировки. Это сделано для того, чтобы мы не загрязняли в Elasticsearch данные нашего технологического журнала данными наших трассировок. Потому что вероятно, что-то может задублироваться или показать какие-то лишние срабатывания.
Мы можем вывести техжурнал в отдельный каталог, настроить отбор (по номеру сеанса, по номеру соединения, по пользователю – как угодно в целом) – это позволяет нам расследовать проблему производительности. Мы эти данные соберем в отдельном индексе, проанализируем, решим, найдем, устраним проблему. И потом мы этот индекс спокойно удаляем – это чисто служебные данные.
Анализ технологического журнала в реальном времени позволяет нам моментально и оперативно реагировать на возникающие проблемы.
Анализируется действительно море информации. У нас в постоянном режиме происходит оповещение мессенджера – что сейчас происходит с базой данных, есть ли блокировки, какие-то Runtime-ошибки.
Кроме этого, Runtime-ошибки мы выводим напрямую в отдельный чат для разработчиков. К сожалению, в 1С не статическая типизация, и возникает очень много Runtime-ошибок, которые просто невозможно предусмотреть (всевозможные «Поле объекта не обнаружено» и т.д.). Эти ошибки моментально выявляются с помощью технологического журнала.
Мониторинг состояния обменов данными
Кроме технологического журнала нам нужно мониторить еще и состояние обменов данными. Для этого у нас есть несколько инструментов, но самый основной и наглядный из них – карта. По сути, это изображение географической карты, на которой отображены все узлы обмена и потоки данных между ними. Как мы видим, карта насыщена узлами обмена, и они, местами, как мы видим, не в очень хорошем состоянии.
На карте каждый узел имеет определенный цвет.
- Если он зеленый, значит, итерация обмена этого узла занимает менее 15 минут времени.
- Если он красный и мигает, то итерация обмена превышает 30 минут, и нам нужно на это как-то реагировать.
- Желтый цвет означает, что мы находимся между 15 и 30 минутами.
Карта интерактивна, она также выводится на большом мониторе, также на вторых мониторах наших коллег. Карта реализована на HTML и JS, а бэкэндом является служебная конфигурация на 1С.
Более подробную информацию о состоянии обменов мы получаем с помощью уже специальных форм плана обмена, которые расположены в конфигурациях. Там мы можем посмотреть информацию о номере отправленного/принятого сообщения, о том, когда в последнее время была запись / чтение. Также там можно в реальном времени увидеть информацию, какой поток из многопоточного чтения сейчас производит чтение, или вдруг идет выгрузка. Также можем быстро посмотреть ошибки, которые возникают.
Если мы видим, что с обменами что-то не так, то с помощью этого инструмента уже более подробно видим, что именно пошло не так. Может быть, просто объем данных увеличился. А может быть, действительно, получили какую-то ошибку, и приходится что-то делать.
И, наконец, если какой-то узел задерживается с обменом на более чем 15 минут, мы получаем уведомления в наши чаты и мессенджеры.
Таким образом, мы оперативно следим за ситуацией с обменами данных и можем моментально решать какие-то возникающие проблемы.
Мониторинг СУБД
Дальше – мы также мониторим ситуацию на СУБД.
- Единственное, что мы можем мониторить – это блокировки и длительные запросы.
- У нас есть несколько инструментов, но основной из них – это десктопное приложение, написанное на C#, которое получает данные о сеансах со всех наших серверов СУБД, и в случае появления конфликтов блокировок или длительных запросов выводит необходимое уведомление на рабочий стол.
- Однако этот инструмент ничего не знает об управляемых блокировках, которые в текущем времени можно мониторить только с помощью технологического журнала или периодически опрашивать консоль серверов. Но так как информация из технологического журнала у нас собирается в режиме реального времени, то все сообщения о проблемах мы получаем моментально. В том числе видим пространство блокировок в случае возникновения ошибок, и какой сеанс кому мешает. Эти оповещения, конечно, происходят не при возникновении какого-то одного конфликта блокировок (это для наших объемов допустимо), но есть определенный уровень, выше которого мы считаем, что уже есть проблемы.
Сбор показателей производительности
Мониторинг работы оборудования и показателей производительности.
- Для сбора показателей производительности работы серверов и оборудования мы используем обычные инструменты, но данные храним в базе данных InfluxDB.
- Для анализа и оперативного оповещения используем Grafana.
Это – классические инструменты, поэтому я думаю, что про них не очень интересно рассказывать.
Сбор собственных метрик
Но однажды перед нами встала интересная задача – бизнес попросил нас реализовать сбор событий открытия форм, но сделать это так, чтобы никак не влиять на систему.
- Мы сразу отказались от очередного регистра сведений или, тем более, журнала регистрации. И решили отправлять произвольные метрики из кода посредством протокола UDP. Это, конечно, спорная тема, но UDP гораздо быстрее, чем TCP. Но 1С не умеет работать с UDP напрямую, поэтому мы реализовали внешнюю компоненту и некий небольшой интерфейс, написанный на 1С, который каждый разработчик может вставлять в свой код и отправлять через UDP определенные данные.
- Метрики мы храним в ClickHouse. Это отличная база данных, но она, к сожалению, тоже не умеет читать протокол UDP.
- Поэтому для чтения UDP мы используем промежуточное звено – это logstash. Он из коробки умеет слушать UDP-порт и принимать на него данные. Также есть плагин, который позволяет выливать данные из logstash в ClickHouse. Его нужно немного покрутить, но он стартует довольно быстро. В итоге мы умеем слать в ClickHouse произвольные метрики прямо из кода, и при этом не создавать почти никакую нагрузку на основную базу данных.
- Единственное, UDP предполагает, что возможны потери пакетов. Но наше нагрузочное тестирование показало, что потери пакетов начинаются только при сверхвысокой нагрузке. Но такая нагрузка – это, видимо, уже совсем другой уровень.
Кроме событий открытия форм, таким образом, мы собираем и замеры времени.
Кстати, ClickHouse очень хорошо умеет агрегировать данные. Мы отсылаем сначала первое событие, а потом, например, после окончания проведения – второе. У них есть одинаковый GUID, и ClickHouse умеет это все клеить, соединять между собой и находить дельту по времени.
Таким образом, мы в текущем времени мониторим, например, время проведения всех документов.
На слайде вы видите хитрый график, выведенный через Grafana. Здесь разноцветными точками представлены различные типы документов. Это – распределение, показывающее, с каким временем происходит проведение этих документов.
Заключение
В итоге наша система мониторинга и те подходы, которые мы применяем, позволяют нам решать быстро и оперативно проблемы, возникающие с производительностью и со стабильностью работы системы. А также иметь данные, на основе которых мы выявляем потенциальные проблемы и предективно их устраняем.
Все те инструменты, о которых я вкратце рассказал, позволяют нашей команде не только обслуживать все системы на платформе 1С в компании ДНС, но и обеспечивать их непрерывную работу, что очень важно для бизнеса, так как мы очень активно используем 1С. Но не все и не всегда работает так, как нужно. Иногда приходится работать и по ночам, и в выходные, и в праздничные дни. Но наши инструменты позволяют решать любые задачи очень быстро.
В заключение могу сказать, что эксплуатировать такую огромную распределенную систему на платформе 1С:Предприятие – это реально.
****************
Данная статья написана по итогам доклада (видео), прочитанного на конференции INFOSTART EVENT 2019.