Стандартная архитектура публикации баз 1С:Предприятие предполагает использование либо Apache (с модулем wsap24.dll), либо IIS (с модулем wsisapi.dll). Однако в высоконагруженных системах или при необходимости специфической настройки маршрутизации разработчики часто задумываются о замене этих компонентов на более гибкие решения, такие как Nginx или серверы, написанные на Golang. Рассмотрим подробнее, как устроено это взаимодействие и с какими трудностями можно столкнуться при попытке "расковырять" интерфейсы 1С.
Для начала проанализируем ситуацию: штатные библиотеки wsap24.dll и wsisapi.dll не являются самостоятельными обработчиками. Они выступают в роли адаптеров между API конкретного веб-сервера и внутренним протоколом кластера 1С. Разберем основные задачи этих модулей:
request_rec в Apache), извлекает заголовки, тело и параметры.v8p.dll) запрос отправляется рабочему процессу 1С.Основная сложность прямой эмуляции этих библиотек заключается в их жесткой привязке к заголовочным файлам Apache или интерфейсам ISAPI. Попытка запустить wsap24.dll вне среды Apache потребует создания сложной "песочницы", имитирующей Apache Runtime (APR), что крайне трудозатратно.
Рассмотрим альтернативный подход: создание собственной внешней компоненты (ВК) на языке Golang, которая будет нести "на борту" полноценный веб-сервер и передавать данные в 1С. Выясним причину, почему это решение кажется привлекательным: Go обладает отличной производительностью в сетевых задачах и позволяет собрать всё решение в одну DLL.
Разберем пример реализации серверной части на стороне Go:
func StartWeb() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if AddInFunc == nil {
fmt.Println("Компонента не инициализирована!")
} else {
// Вызываем Callback функцию, которая отправит событие в 1С
C.invoke(C.closure(AddInFunc))
}
// В этой точке возникает главная архитектурная проблема:
// как дождаться ответа от кода 1С, чтобы записать его в Response?
w.Write([]byte("Запрос принят 1С, но ответ еще не готов."))
})
port := "1111"
if err := http.ListenAndServe(":"+port, nil); err != nil {
fmt.Println(err)
}
}
На стороне C++ (прослойка для Native API) передача события в 1С выглядит следующим образом:
VOID CALLBACK Event() {
if (!pAsyncEvent)
return;
wchar_t *who = L"CustomWebServer", *what = L"HttpRequest";
wchar_t *wsdata = L"Method: GET, Path: /api/data";
// Отправка асинхронного события в 1С
pAsyncEvent->ExternalEvent(who, what, wsdata);
}
Проанализируем ситуацию, с которой сталкиваются все разработчики при использовании ExternalEvent. Метод ВнешнееСобытие в 1С работает через очередь сообщений Windows. Это означает, что:
pAsyncEvent->ExternalEvent не блокирует поток в Go/C++. Он просто ставит событие в очередь 1С.ВнешнееСобытие выполнится тогда, когда платформа "освободится".Для полноценного HTTP-сервера это критично, так как клиент ожидает HTTP-ответ (200 OK, 404 и т.д.) немедленно. Если мы отправим ExternalEvent, поток Go пойдет дальше и завершит HTTP-сессию раньше, чем 1С успеет обработать данные.
Чтобы обойти ограничения асинхронности, проанализируем следующие способы:
УстановитьРезультат(Данные)), который заполняет эту переменную и "отпускает" поток ожидания в Go.wsap24.dll, мы ставим Nginx перед стандартным Apache. Nginx берет на себя SSL, фильтрацию запросов и балансировку, а Apache выступает лишь в роли легковесного адаптера для передачи запроса в 1С.com.1c.v8.web.server.jar может дать ключ к пониманию того, как сформировать запрос к кластеру напрямую, минуя бинарные модули Apache.Если вы все же решили пилить нативную компоненту на Go, разберем по шагам, как минимизировать накладные расходы:
Шаг 1: Используйте cgo для связи Go и Native API. Помните, что DLL на Go может быть довольно объемной (от 10-15 МБ), так как включает в себя среду выполнения (runtime).
Шаг 2: Реализуйте в ВК метод, который 1С будет вызывать для возврата результата. Например, ВернутьОтвет(ИдентификаторЗапроса, ТелоОтвета).
Шаг 3: На стороне Go используйте sync.Map для хранения каналов (channels) под каждый входящий запрос по уникальному ID. После отправки события в 1С, Go-рутина блокируется на чтении из канала:
// Псевдокод ожидания ответа в Go
respChan := make(chan string)
requestsMap.Store(requestId, respChan)
C.invoke_event(requestId) // Отправляем в 1С через ВК
// Ждем ответа из 1С (с таймаутом)
select {
case response := <-respChan:
w.Write([]byte(response))
case <-time.After(30 * time.Second):
w.WriteHeader(504)
}
Вывод: Прямая эмуляция wsap24.dll практически невозможна без глубокого реверс-инжиниринга закрытых протоколов 1С. Однако использование Nginx как прокси или написание собственной ВК на Golang с механизмом блокирующих каналов — это вполне рабочие стратегии для создания кастомных интерфейсов взаимодействия с платформой.