Предисловие
Статья вдохновлена публикацией IIS? Apache? А может быть, Node.js?. Рекомендую сначала прочитать её, а потом уже мой "отчет об эксперименте".
Проблема
Наткнувшись недавно на статью IIS? Apache? А может быть, Node.js? я узнал о новом способе обработки HTTP запросов, о котором я даже никогда не задумывался. Суть была в том, что бы использовать в качестве обработчика HTTP запросов не 1С, а Node JS, в коде которого создается COM соединение с 1С которое выполняет в себе обработку запроса. Идея прекрасна, так как в таком раскладе можно использовать NGINX, который гораздо лучше ведет себя в нагрузках, да и в целом он более современный и является де-факто в современном мире WEB.
В комментариях основной претензией к такому способу стало использование COM объекта, так как этот механизм стар и уже изжил своё (с чем я не могу не согласится). И я задумался о том, как еще можно обрабатывать HTTP запросы в 1С не используя HTTP сервисы.
Идея
Мне пришла в голову идея: что если создать сервис, который будет принимать на себя HTTP запросы и иметь HTTP интерфейс для обработки этих запросов.
Алгоритм следующий:
- Запрос, например /test попадает в Сервис обработки запросов (далее СОЗ) и ждёт, когда его смогут обработать.
- В 1С запущен фоновый обработчик (или обработчики, что бы увеличить количество потоков обработки), который в бесконечном цикле делает long-polling запрос к СОЗ (например /request) и ждёт от него запрос для обработки.
- 1С получает в ответ на /request запрос для обработки с какими то данными, что-то с ними делает и снова отправляет HTTP запрос в СОЗ (например /response) с результатом обработки.
- СОЗ получает результат обработки и отвечает клиенту.
Реализация
Для написания простейшего СОЗ я выбрал Go так как он, по моему мнению, лучше всего подходит для этих целей. Он "простой", быстрый, надежный и многие позиционируют его как язык для написания микросервисов, коим наш СОЗ и является.
Сервис написан в стиле "простыня" или "на коленке" и не является "production ready" решением. Если хотите использовать его для себя, то необходимо внести доработки: сделать хоть какую то модульность, предусмотреть обработку ошибок, логирование и т.д.
На стороне 1С реализация тоже максимально простая:
API.Тест(...) делает довольно простую работу: немного математики, преобразование в JSON, один запрос константы. Но в нагрузке способен заставить поработать процессор, что нам и нужно. При N = 1000 на моей машине этот код выполняется ~10мс.
Тесты
Для тестирования я использовал свой рабочий компьютер
Для нагрузки на API использовался k6. Настройка простая: тестируется один путь, 50 виртуальных пользователей в течении 5-ти минут.
import http from 'k6/http';
import { randomString } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';
export const options = {
duration: "5m",
vus: 50,
};
export default function () {
const body = randomString(1, 30)
http.post('http://localhost:8090/test', body);
}
Для тестирования классического HTTP сервиса конфигурация такая же, только другой путь к конечной точке.
Классический HTTP сервис:
Обработка через СОЗ (10 потоков обработчиков запросов):
Выводы
Результаты тестирования показали, что обработка запросов через СОЗ дало ~20% прироста производительности в рамках req/s (запросы в секунду). Так же можно увидеть значительное улучшение результатов во времени обработки запроса.
Так же во время тестирования я наблюдал за нагрузкой на систему и в связке СОЗ + 1С можно заметить больший процент утилизации процессора rphost'ом ~89-93% против ~71-75%, что скорее всего и дало положительные результаты по производительности.
Еще из положительных аспектов: работа через СОЗ дает контролируемое количество сеансов 1С.
Из минусов: повышенная сложность алгоритма обработки запроса и баги, которые пока еще не выявлены.
Для кого подошло бы такое решение?
Наверное только для тех, у кого есть большие нагрузки на HTTP сервис, который дает просадки по производительности, случайные длинные ответы и другие артефакты HTTP сервисов от 1С.
P.S.
В архиве, приложенном к статье, лежит файл GO, файлы k6 и dt базы в которой я делал тестирование.