Опыт работы «1С:ERP» в ландшафте Linux + PostgreSQL – 7 лет
В связи с обострением вопросов импортозамещения многие задумываются о переходе на системы, позволяющие заменить зарубежные аналоги, или уже его начали. Мы решили поделиться с вами 7-летним опытом установки и эксплуатации системы Linux + PostgreSQL + «1C» на 300 онлайн-пользователей.
Авторы статьи:
Александр Стрижевский – начальник ИТ-отдела АО «123 авиаремонтный завод»* («123 АРЗ»)
Дмитрий Малышев – разработчик в ВЦ «Раздолье», «1С»-эксперт по технологическим вопросам
*АО «123 АРЗ» - одно из ведущих предприятий по ремонту и техническому обслуживанию транспортных самолётов военной и гражданской авиации России. Широкий спектр услуг с применением передовых технологий, тесное сотрудничество с разработчиками авиационной техники, адекватность потребительскому спросу и высокое качество ремонта – главные приоритеты предоставляемых услуг. Нам доверяют ремонт авиационной техники не только российские, но и зарубежные авиакомпании, расположенные на трёх континентах.
Начнём с опыта установки и эксплуатации системы Linux.
Сегодня использование альтернатив Microsoft не имеет каких-то нерешаемых проблем или серьёзных рисков. Комбинация Linux + PostgreSQL является хорошей платформой для информационной системы на базе программных продуктов «1С», но так было не всегда.
Эволюция программного и аппаратного обеспечения
К 2015 году предприятие работало с базами на платформе «1С» 7.7 по складскому учёту. Базы работали на MS SQL 6.5. Покупали тогда бандлом «1С» + SQL под конфигурацию «ЗиК». Затем приобрели программу «1С:Бухгалтерия 8». Поскольку её использовали онлайн всего 10 пользователей, ставить под такую задачу сервер MS SQL было неоправданно дорого. Это послужило тестированием работы «1С:Бухгалтерии 8» на Linux + PostgreSQL. Тесты прошли успешно – всё работало хорошо.
В 2016 году предприятие запустило проект внедрения «1С:ERP», и в этот момент ребром встал вопрос выбора – на каком системном программном обеспечении запускать такую большую и нагруженную систему. Уже тогда наш завод посчитал, что стоимость лицензий SQL и пользовательских лицензий на доступ от Microsoft слишком высока. Учитывая успешный опыт использования PostgreSQL и Linux для работы «1С:Бухгалтерии 8», решили использовать это бесплатное ПО и для запуска «1С:ERP». Как показывает опыт и текущая ситуация, решение было верным, т.к. в настоящий момент благодаря ему нас не заботит решение вопросов импортозамещения в авральном режиме.
С самого начала проекта внедрения «1С:ERP» сразу запускался в комбинации: сервер «1C» + Linux + PostgreSQL. Вначале в системе работало до 40 пользователей и всё было хорошо – время отклика соответствовало ожиданиям. Но когда количество активных пользователей превысило 50, система начала тормозить. Беглый анализ показал, что причиной проблемы стало использование старого «железа» и виртуализации. Тогда было принято решение приобретать новые сервера, которые выбрали по рекомендации интегратора [ВЦ «Раздолье»].
Были приобретены 2 сервера HP со следующими характеристиками: 256 Гб оперативной памяти, диски 2х800 Гб NVME SSD, процессоры 2х12 ядер по 2 потока (48 потоков). Один «железный» сервер выделен под сервер «1С», другой – под PostgreSQL. Серверы соединены каналом в 10 Gb.
На новых серверах решили задействовать не виртуальные машины, а автономные контейнеры в локальной среде (docker'ы). В настоящий момент планируем в дальнейшем использовать системы Kubernetes [открытое программное обеспечение для «оркестровки» контейнеризированных приложений — автоматизации их развёртывания, масштабирования и координации в условиях кластера]. На системе докеров остановились в связи с тем, что она требует меньше дополнительных расходов аппаратных ресурсов и работает быстрее виртуализации. Докеры взаимодействуют друг с другом через индивидуальные ip-адреса и диапазоны портов.
На серверах использовали Centos 7, PostgrePro, сервера «1С» х64.
Сервер под «1С»
«Железный» сервер разделен на 10 doker'ов:
1 докер используется для работы исторических баз: «1С:Бухгалтерия 8», «1С:Общепит», «Метрология».
3 doker'a используются для работы кластера из 3 серверов «1С» с резервированием для рабочей базы «1С:ERP» [сейчас онлайн – 250 пользователей].
1 докер используется для работы тестовой базы «1С:ERP».
2 doker'a используются для работы кластера из 2 серверов «1С» для рабочей базы «1С:Зарплата и управление персоналом 8» [35 пользователей онлайн].
1 докер используется для работы тестовой базы «1С:Зарплата и управление персоналом 8».
1 докер используется для работы базы «Казначейства» на «1С».
1 докер используется как СЛК-сервер для системы «1С:Общепит».
В докерах «1С» обычно используем самые последние платформы с сайта технической поддержки «1С».
Сервер под PostgreSQL
Этот сервер также разбит на docker'ы. Под каждый кластер «1С» выделяем отдельный докер на втором сервере.
На сервере стоит версия PostgreSQL с cайта команды Postgres Professional, где есть сборки специалистов для «1С» (не с сайта «1С»). Здесь есть возможность скачать более свежие сборки и релизы «Постгрес».
Установка
На старых «железных» серверах продолжили использовать виртуальные машины Linux, на новых – сразу решили использовать doker'ы.
По статистике на разворачивание сервера Linux уходит примерно 1,5 часа.
Разворачивание подсистемы докеров из репозитария на серверах занимает пару минут (см. инструкцию). Сборка образа с использованием docker-файлов занимает 5-10 минут. Мы используем только 2 docker-файла: один – для серверов «1С», второй – для Postgres.
Построенный образ на остальные docker'ы просто копируется. Настроенные docker-файлы с описанием последовательности шагов установки [ставится образ «Линукса», пакеты ПО, пути к дистрибутивам «1С» и Postgres] можно посмотреть в «Приложении».
Если в дальнейшем потребуется разворачивать большое количество докеров, то можно будет использовать Ansible — систему управления конфигурациями, написанную на Python, с использованием декларативного языка разметки для описания конфигураций. Это позволит автоматизировать настройки и развертывание программного обеспечения.
Администрирование
Сопровождают 20 образов докер в нашем случае 2 администратора. Работаем с Docker в консоли. Также использовали GUI-/веб-интерфейс. Для помощи администратору в случае необходимости существуют и красивые «мышкадавы», которые сами работают в докере и помогают управлять другими докерами. Но, в основном, они полезны в случаях, если существует «зоопарк» из десятков или сотен разнонаполненных докеров.
В статье на «Хабре» представлен обзор наиболее заметных на сегодняшний день графических интерфейсов для обслуживания Docker:
-
Portainer
-
Kitematic (Docker Toolbox)
-
Shipyard
-
и т.д.
Так как у нас используется всего 2 шаблона докера [один – под «1С», другой – под PostgreSQL] – их администрирование из стандартной консоли из поставки не представляет сложности.
Docker'ы сервера «1С»
Docker'ы сервера PostgreSQL
PGAdmin, кстати, тоже запущен в контейнере docker.
Плюс используются утилиты мониторинга Linux.
Время работы системы 1857 дней.
Регламентное обслуживание
Обслуживание для докеров с «1С» в основном сводится к перезапуску службы сервера «1С», что занимает 5 секунд. Также используем обрезание журналов регистрации «1С» [Раньше для экономии лицензий использовали отключение спящих сеансов, пока в конфигурации не задействовали настройку отключения спящих сеансов и не сменили её значение с 48 на 10 часов].
Для докеров с PostgreSQL используем обновление статистик, обновление индексов и резервное копирование. Резервное копирование идёт на отдельный «железный» сервер № 3, предназначенный для хранение резервных копий данных.
Ещё выполняется обслуживание Cron'ами (скриптами). Cron-программы [в системах класса UNIX], используются для периодического выполнения заданий в определённое время. Регулярные действия описываются инструкциями, помещёнными в файлы crontab и в специальные каталоги. Выполняются по расписанию.
Лицензирование
В нашем случае стоят аппаратные лицензии «1С». Это исторически сложившаяся традиция со времени использования виртуальных машин.
Программные лицензии также могут успешно использоваться в докерах вместо аппаратных.
Сервер лицензирования и СЛК-сервер можно установить в отдельных докерах. И они будут видны в остальных докерах по отдельным IP [используется macvlan сетевой драйвер docker для назначения MAC адрес к виртуальному сетевому интерфейсу каждого контейнера, что делает его похожим на физический сетевой интерфейс, напрямую подключенный к физической сети].
Опыт решения проблем
Платформа «1С:Предприятие 8» и конфиугурации «1С:ERP» и «1С:ЗУП» в ходе эксплуатации потребовали оптимизации.
Расскажем о нескольких случаях из практики.
Пример 1: Оптимизация закрытия месяца
Сложилась ситуация: закрытие периода в «1С:ERP» в базе на MS SQL проходило за 1 час, при этом в базе на PostgreSQL — за 6 часов.
Проблема оказалась комплексной:
-
алгоритмы закрытия месяца кешировали избыточное количество данных, что вело к сильным замедлениям;
-
настройки PostgreSQL были неоптимальны;
-
была ошибка в самой платформе «1С».
К решению приступали параллельно с поддержкой фирмы «1С».
По итогу от «1С» получили рекомендацию по изменению настроек PostgreSQL:
«Поскольку в ускоренном расчёте себестоимости самый долгий этап – СкорректироватьСтоимостьСписанияНезавершенногоПроизводства, потому анализ начали с него. Большая часть времени этап выполняется на СУБД.
Анализ планов запросов показал следующие проблемы:
- Долгое выполнение ANALYZE для временных таблиц. Длительность ANALYZE не коррелирует с размером таблиц. maintenance_work_mem 2GB. Увеличение длительности происходит из-за default_statistics_target = 1000, согласно документации "Чем больше установленное значение, тем больше времени требуется для выполнения ANALYZE, но тем выше может быть качество оценок планировщика. Значение этого параметра по умолчанию — 100". Рекомендуем вернуть значение по умолчанию (100).
- Нехватка work_mem. Чаще всего проявляется в случаях, когда необходимо выполнить сортировку или агрегацию для большого числа строк. Из-за нехватки work_mem postgres обращается к диску и выполняет действия на нём, что существенно сказывается на времени выполнения запросов. Текущее значение work_mem 256MB, рекомендуем его увеличить до 512MB или 1GB при наличии возможностей».
Своими силами для поиска проблем производительности мы настроили сбор данных технологического журнала «1С» + логирование в PostgreSQL. Далее – выполнили определение проблемных запросов и корректировку кода в программе «1С:ERP». В качестве навигатора действий поиска и отладки использовали статьи и инструменты с «Инфостарта», GitHub и «Тензор»:
-
Пример пошагового решения проблемы производительности на базе PostgreSQL с картинками: //infostart.ru/1c/articles/1611069/;
-
Исправляем проблемы производительности в конфигурации ERP - 7 примеров: //infostart.ru/1c/articles/1611545/;
-
Инструменты лежат на GitHub:
https://github.com/Polyplastic/1c-parsing-tech-log;
-
Визуализации планов запросов PostgreSQL: Self-hosted EXPLAIN: наглядно и безопасно: https://habr.com/ru/company/tensor/blog/677948/.
Найденные решения заключались в следующем:
-
При закрытии «1С» либо кешировало избыточное количество данных во временные таблицы, либо для них не было подходящих индексов. Исправление заключалось в преобразовании типовых временных таблиц в свои с меньшим объемом данных и создании подходящих индексов;
-
Также была зарегистрирована ошибка в платформе «1С», связанная с отсутствием подходящего индекса для внутриплатформенного метода апдейта данных.
Ошибка 60001790 исправлена и уже опубликован релиз платформы, содержащий исправление.
https://releases.1c.ru/version_files?nick=Platform83&ver=8.3.21.1508
В итоге мы достигли ускорения закрытия периода в «1С:ERP» с 6 до 1,5 часов.
Пример 2: Ошибка с платформой и обновлением конфы
В 8.3.19 столкнулись с падением фоновых заданий, в 8.3.20 – отладка не работала с фоновыми процессами, в 8.3.21 – падает сама «1С» при работе на старых машинах с ОС Windows XP (ошибка 60003943).
Несколько раз при обновлении падала конфигурация «1С». Не могла завершиться транзакция. Откатили её в таблице config [некоторые решения на форумах для MS SQL также подходят для PostgreSQL].
Пример 3: Медленная работа «1С:ЗУП» при использовании RLS
Реализации RLS [ограничение прав доступа в «1С» на уровне записей] под PostgreSQL была недостаточно производительной. Устранили эту проблему так же по рекомендациям фирмы «1С». Суть: выгрузка ролей в файлы и глобальной заменой запросов ограничений, затем загрузка файлов обратно. Делали так при каждом обновлении «1С:ЗУП», начиная с платформы 8.3.16.
В настоящий момент система RLS в платформе и конфигурации «1С:ЗУП» работает под PostgersSQL с нормальной производительностью. В текущих версиях платформы «1С:Предприятие 8» [начиная с 8.3.20] механизм RLS уже оптимизирован и замены в «1С:ЗУП» не требуется. Изменилась трансляция запросов, они стали быстрее обрабатываться в Postgres'е.
Feedback от эксплуатации и пожелания
В настоящее время использование свободного ПО для работы «1С:ERP» – штатная ситуация. Платформа и программные продукты «1С» развиваются в сторону адаптации и стабильной работы со связкой Linux и PostgreSQL. Сейчас можно смело рекомендовать использовать это свободное программное обеспечение для работы «1С». Тем не менее есть некоторые направления, по которым от «1С» хотелось бы улучшения контента.
Приложения
Приложение 1: Оптимизация закрытия месяца
Ставим последнюю версию платформы «1С»
PG main.conf:
# Memory Settings
shared_buffers = 32GB
work_mem = 512MB
maintenance_work_mem = 2GB
effective_cache_size = 96GB
PG stat.conf:
default_statistics_target = 100
PG log.conf:
auto_explain.log_min_duration = '20s'
В конфигурации мониторинга загружаем ТЖ:
Находим по временной метке запрос в логе PostgreSQL и через обработку КонверторЗапросовSQL_в_«1С» получаем красивый план:
см. Explain PostgreSQL (tensor.ru)
Далее по строке ТЖ получаем:
В модуле Общий модуль РасчетСебестоимостиРешениеСЛУ:
Функция ТекстДляРешенияСЛУ_ДополнительныеРасходы(ПараметрыРасчета = Неопределено)
... ТекстыЗапросов.Добавить(РасчетСебестоимостиКорректировкаСтоимости.ТекстСуммыПрочихРасходов());
Далее ТекстСуммыПрочихРасходов() ищем похожее на:
И находим:
...
|ПОМЕСТИТЬ СуммыРасходов|ИЗ
| (ВЫБРАТЬ
...
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
...
| ИЗ
| ВТКэшРасчетныеОборотыПрочиеРасходы КАК ДД
|
| ЛЕВОЕ СОЕДИНЕНИЕ РассчитанныеДокументы КАК РассчитанныеДокументы
| ПО РассчитанныеДокументы.Период = ДД.Период
| И РассчитанныеДокументы.Регистратор = ДД.Регистратор
...
| ЛЕВОЕ СОЕДИНЕНИЕ ВТКэшРасчетныеОборотыСебестоимостьТоваров КАК ДвиженияСебестоимости
| ПО ДвиженияСебестоимости.Период = ДД.Период
| И ДвиженияСебестоимости.Регистратор = ДД.Регистратор
| И ДвиженияСебестоимости.ИдентификаторФинЗаписи = ДД.ИдентификаторФинЗаписи
...
В протоколе закрытия месяца:
35. Партионный учет: ПодготовкаДанныхДляРешенияСЛУ_ДополнительныеРасходы
Начало этапа: 08.09.2022 11:16:17, длительность: 3 мин. 30,391 сек. (11,32%)
Время от начала расчета до начала этапа: 10 мин. 55 сек.
Сформированы временные таблицы (размер / время (% времени этапа) / уточнение / исходные таблицы):
...
- СуммыРасходов:
- 2 409 / 3 мин. 30,148 сек. (99,88%)
...
57. Партионный учет: ПодготовкаДанныхДляРешенияСЛУПостатейныеРасходы
Начало этапа: 08.09.2022 11:23:19, длительность: 3 мин. 43,8 сек. (12,04%)
Время от начала расчета до начала этапа: 17 мин. 57 сек.
Сформированы временные таблицы (размер / время (% времени этапа) / уточнение / исходные таблицы):
…
- СуммыРасходов:
- 2 409 / 3 мин. 36,445 сек. (96,71%)
…
Вот ОНО!
Продолжение – в следующей серии...
По плану: https://explain.tensor.ru/archive/explain/4f2600615440c6fba8c18d21ff9a6e58:0:2022-09-08#visio
Есть рекомендация:
Создаём временную таблицу с индексацией по полям, по которым соединяются таблицы:
|ВЫБРАТЬ
| ДД.Период КАК Период,
| ДД.Регистратор КАК Регистратор,
| ДД.ИдентификаторФинЗаписи КАК ИдентификаторФинЗаписи,
| ДД.НастройкаХозяйственнойОперации КАК НастройкаХозяйственнойОперации,
| ДД.ХозяйственнаяОперация КАК ХозяйственнаяОперация,
| ДД.АналитикаУчетаНоменклатуры КАК АналитикаУчетаНоменклатуры,
| ДД.РазделУчета КАК РазделУчета,
| ДД.ВидЗапасов КАК ВидЗапасов,
| ДД.Организация КАК Организация,
| ДД.Партия КАК Партия,
| ДД.АналитикаУчетаПартий КАК АналитикаУчетаПартий,
| ДД.АналитикаФинансовогоУчета КАК АналитикаФинансовогоУчета,
| ДД.ВидДеятельностиНДС КАК ВидДеятельностиНДС
|
|ПОМЕСТИТЬ ВТРасчетныеОборотыСебестоимостьТоваров3557
|
| ИЗ
| ВТКэшРасчетныеОборотыСебестоимостьТоваров КАК ДД
|
|ИНДЕКСИРОВАТЬ ПО
| Период,
| Регистратор,
| ИдентификаторФинЗаписи,
| НастройкаХозяйственнойОперации,
| ХозяйственнаяОперация
Результат: https://explain.tensor.ru/archive/explain/561584559eccb0d869e186ab5d152b37:0:2022-09-09#visio
Итого: 209 721.150 / 8.420 = 24907,5, ускорение примерно в 25000 раз.
Приложение 2. Примеры файлов для запуска docker'а
Dockerfile.21
# vim:set ft=dockerfile:
FROM sav/basicsystem1c-7:build
MAINTAINER sav
ARG SERVER_1C_VERSION
COPY ./distr/setup-full-${SERVER_1C_VERSION}-x86_64.run /tmp/
RUN ./tmp/setup-full-${SERVER_1C_VERSION}-x86_64.run --unattendedmodeui minimalWithDialogs --mode unattended --enable-components server,config_storage_server,ru \
&& rm -rf /tmp/*
VOLUME /home/usr1cv8
VOLUME /tmp/.aksusb
# && echo "SystemLanguage=RU" > /opt/1cv8/conf/conf.cfg \
# && chown -R usr1cv8:grp1cv8 /opt/1cv8 \
#RUN mkdir -p /home/usr1cv8/.1cv8/1C/1cv8/conf/
#COPY logcfg.xml /home/usr1cv8/.1cv8/1C/1cv8/conf/
#RUN chown -R usr1cv8:grp1cv8 /home/usr1cv8
COPY docker-entrypoint.sh.18 /docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE 1540-1541 1560-1591
CMD ["ragent"]
Docker-compose.yml
version: '2.2'
networks:
macvlan1:
external:
name: macvlan1
netcont0:
external:
name: netcont0
services:
1C:
build:
context: ../Docker/srv-1C
dockerfile: Dockerfile
args:
- SERVER_1C_VERSION=${VERSION_1C}
image: sav/srv-1c:${VERSION_1C}
container_name: srv-1C-${ContainerName}
hostname: srv-1C-${ContainerName}
networks:
macvlan1:
ipv4_address: $srv1C_IP1
netcont0:
ipv4_address: $srv1C_IP2
dns_opt:
- ndots:1
volumes:
- /etc/localtime:/etc/localtime:ro
- /tmp/.aksusb:/tmp/.aksusb
- /opt/1C/home/${ContainerName}:/home/usr1cv8
- /opt/1C/ХранилищеФайлов/N1:/home/usr1cv8/ХранилищеФайлов
# - /etc/hasplm/nethasp.ini:/etc/nethasp.ini:ro
mem_limit: $MEM_LIMIT
# lscpu | grep node1
cpuset: $CPU_SET
tmpfs: /tmp:rw,exec,strictatime
extra_hosts:
- srv-db1C-${ContainerName}:$srvDB_IP1
restart: always
environment:
- SERVER_1C_VERSION=${VERSION_1C}
- DEBUG=-debug
- TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES=${TCMALLOC_THREAD_CACHE}