Интеграция большого количества розничных точек (в нашем случае около 400 магазинов) с центральной ERP-системой — задача всегда непростая. Ситуация существенно осложняется, если на точках установлена устаревшая платформа 1С 7.7, компьютеры не обладают высокой производительностью, связь осуществляется через нестабильный 4G-интернет, а у магазинов отсутствуют статические («белые») IP-адреса. В таких условиях стандартный подход — прямой регулярный опрос (polling) центральной ERP-системы каждую минуту — быстро вызовет перегрузку веб-сервера и базы данных ERP из-за огромного количества холостых запросов.
Разберем детально, как решить эту проблему, не перегружая центральную систему, избегая сложного администрирования локальных веб-сервисов на каждой точке и обеспечивая максимальную отказоустойчивость всей архитектуры.
Если 400 торговых точек будут ежеминутно обращаться к центральной ERP по протоколам SOAP или JSON, база данных будет вынуждена обрабатывать 24 000 запросов в час только ради того, чтобы ответить «Для вас новых задач нет». Это приводит к бессмысленному расходу вычислительных ресурсов. Кроме того, при использовании мобильного 4G-интернета сетевые сессии часто обрываются, что вызывает зависание процессов интеграции в самой 1С 7.7.
Давайте проанализируем наиболее эффективные архитектурные решения этой задачи, начиная от простых микросервисов-посредников и заканчивая проверенными временем технологиями гарантированной доставки данных.
---
Один из самых надежных и простых в поддержке способов снизить нагрузку на ERP — это вынесение логики очередей на отдельный сверхлегкий промежуточный сервер (прокси-сервер). ERP сообщает этому серверу о наличии изменений для конкретного магазина, а магазины опрашивают не тяжелую ERP, а этот сверхбыстрый буфер.
Напишем и разберем простейший пример такого сервера на языке Go (Golang). Этот язык компилируется в один исполняемый файл, практически не потребляет оперативную память и способен обрабатывать десятки тысяч запросов в секунду на самом дешевом хостинге.
package main
import (
"net/http"
"strings"
"sync"
)
// Безопасное хранилище для статусов задач магазинов
var (
mlist = make(map[string]string)
mu sync.Mutex
)
func main() {
// Установка флага задачи для магазина из ERP
// Пример запроса: http://server/setevent/100500/new_task_id
http.HandleFunc("/setevent/", func(w http.ResponseWriter, r *http.Request) {
sp := strings.Split(r.URL.Path, "/")
if len(sp) >= 4 {
mg := sp[2] // ID магазина
ev := sp[3] // ID или тело задачи
mu.Lock()
mlist[mg] = ev
mu.Unlock()
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
} else {
http.Error(w, "Bad Request", http.StatusBadRequest)
}
})
// Получение задачи магазином
// Пример запроса: http://server/getevent/100500
http.HandleFunc("/getevent/", func(w http.ResponseWriter, r *http.Request) {
sp := strings.Split(r.URL.Path, "/")
if len(sp) >= 3 {
mg := sp[2]
mu.Lock()
v, ok := mlist[mg]
if ok && v != "" {
w.Write([]byte(v))
mlist[mg] = "" // Сбрасываем флаг после получения
} else {
w.Write([]byte("")) // Задач нет
}
mu.Unlock()
} else {
http.Error(w, "Bad Request", http.StatusBadRequest)
}
})
// Запуск сервера на порту 8080
http.ListenAndServe(":8080", nil)
}
Как работает эта схема:
/setevent/100500/task_01./getevent/100500.---
Если мы хотим избавиться от периодического опроса вообще, нам отлично подойдет технология Long Polling (длинные опросы). При этом подходе 1С делает запрос к серверу, а сервер не отвечает сразу, а удерживает соединение открытым до тех пор, пока не появится задача для этого магазина (или не истечет таймаут, например, 50 секунд).
Для реализации длинных опросов в 1С 7.7 мы можем использовать стандартный системный объект MSXML2.ServerXMLHTTP, который поддерживает асинхронные запросы без блокировки интерфейса пользователя.
Рассмотрим пример кода в глобальном модуле или обработке 1С 7.7:
Перем ПолучательЗапросов;
Процедура ИнициализироватьДлинныйОпрос()
ПолучательЗапросов = СоздатьОбъект("MSXML2.ServerXMLHTTP.6.0");
// Укажем таймаут ожидания (например, 60 секунд)
ПолучательЗапросов.setTimeouts(5000, 5000, 55000, 55000);
// Подключаемся к буферному серверу в асинхронном режиме (третий параметр - Истина)
ПолучательЗапросов.open("GET", "http://my-buffer-service.ru/getevent/100500", 1);
ПолучательЗапросов.send();
// Запускаем периодическую проверку завершения запроса через встроенный таймер 1С
ОбработкаОжидания("ПроверитьРезультатЗапроса", 2);
КонецПроцедуры
Процедура ПроверитьРезультатЗапроса()
// Проверяем состояние готовности (readyState = 4 означает выполнение запроса)
Если ПолучательЗапросов.readyState = 4 Тогда
// Отключаем обработку ожидания на время анализа данных
ОбработкаОжидания("ПроверитьРезультатЗапроса", 0);
Если ПолучательЗапросов.status = 200 Тогда
Результат = ПолучательЗапросов.responseText;
Если ПустаяСтрока(Результат) = 0 Тогда
// Получен реальный сигнал о задаче!
ОбработатьНовуюЗадачу(Результат);
КонецЕсли;
КонецЕсли;
// Сразу же запускаем новый длинный запрос для непрерывного ожидания
ИнициализироватьДлинныйОпрос();
КонецЕсли;
КонецПроцедуры
Преимущества Long Polling: сетевое соединение всегда инициирует клиент (магазин), что решает проблему отсутствия белых IP-адресов. При этом событие от ERP доставляется на точку практически мгновенно без создания паразитного трафика.
---
Если связь на точках действительно критически нестабильна (постоянные обрывы сессии посреди передачи файлов), то классические веб-сервисы могут дать сбой. В таких случаях стоит обратиться к технологиям, создававшимся специально для работы по плохим каналам связи — почтовым FTN-клиентам (майлерам), таким как binkd или Radius FTN-mailer.
Как организовать такую архитектуру:
Главные плюсы FTN-технологий:
---
Еще один современный и крайне эффективный паттерн для IoT и распределенных сетей — это использование протокола MQTT (например, брокера Eclipse Mosquitto) вместо тяжелого RabbitMQ.
Протокол MQTT работает по принципу "издатель-подписчик" (Pub/Sub) и идеально подходит для условий с плохой связью. Для интеграции с 1С 7.7 на клиенте можно использовать ActiveX-компоненту работы с сокетами или готовые библиотеки интеграции с MQTT. 1С подписывается на топик shops/100500/tasks и переходит в режим ожидания. Брокер сам удерживает соединение, потребляя всего несколько байт в минуту на поддержание сессии (Keep-Alive). При появлении сообщения брокер моментально проталкивает его на клиент, где 1С перехватывает его через процедуру ВнешнееСобытие().
---
Выясним, какое решение лучше выбрать в зависимости от приоритетов вашей команды разработки:
MSXML2.ServerXMLHTTP.Любой из этих подходов позволит вам успешно связать 400 розничных точек на старой платформе 1С 7.7 с современной ERP, обеспечив надежную работу бизнеса без переплат за серверные мощности и дорогостоящее администрирование.