При разработке современных систем на платформе 1С:Предприятие 8.3 часто возникает архитектурная задача: одна база должна запрашивать данные из другой через HTTP-сервисы. Ситуация осложняется, когда основной пользователь работает через веб-клиент, а обе базы (источник и приемник) являются файловыми и опубликованы на одном веб-сервере Apache. В этой статье мы подробно разберем, почему возникает ошибка «Не могу установить соединение» и как правильно настроить взаимодействие между базами.
Рассмотрим стандартную ситуацию. У нас есть две базы. В первой базе (клиентской) написан код, который на сервере инициирует HTTPСоединение ко второй базе (сервисной). При запуске через тонкий клиент все отрабатывает успешно, но при входе через браузер (веб-клиент) тот же самый код выдает ошибку: «Ошибка работы с Интернет: Не могу установить соединение».
Проанализируем причину. Несмотря на то, что код выполняется в процедуре &НаСервереБезКонтекста, окружение веб-клиента накладывает свои ограничения. Когда сервер 1С первой базы пытается обратиться к localhost, на котором работает Apache, возникает конфликт ресурсов или сетевых разрешений внутри самого процесса веб-сервера. Для файловых баз на одном Apache это часто приводит к «зацикливанию» (deadlock) потоков исполнения.
Самый надежный способ решить проблему — исключить ситуацию, когда Apache пытается вызвать сам себя в рамках одного и того же сетевого адреса и порта. Рассмотрим, как это можно реализовать:
Выясним причину, почему localhost может подводить. Зачастую система пытается разрешить имя localhost через протокол IPv6 (адрес ::1), в то время как публикация 1С ожидает IPv4 (127.0.0.1). Посмотрим на пример правильной инициализации соединения:
&НаСервереБезКонтекста
Процедура ВыполнитьЗапросНаСервере()
// Вместо "localhost" используем явный IP-адрес
СерверИсточник = "127.0.0.1";
Порт = 80;
АдресРесурса = "/Base2/hs/v1/getData/";
// Принудительно устанавливаем заголовки для закрытия соединения
Заголовки = Новый Соответствие;
Заголовки.Вставить("Connection", "close");
НТТР = Новый HTTPСоединение(СерверИсточник, Порт, , , , 30);
Запрос = Новый HTTPЗапрос(АдресРесурса, Заголовки);
Попытка
Ответ = НТТР.Получить(Запрос);
Сообщить("Код состояния: " + Ответ.КодСостояния);
Исключение
Сообщить("Ошибка: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Использование заголовка Connection: close крайне важно в сценарии с одним сервером. Это заставляет веб-сервер закрывать соединение сразу после ответа, не дожидаясь тайм-аута Keep-Alive, что освобождает потоки Apache для новых запросов.
Проанализируем альтернативный подход. Платформенный объект HTTPСоединение обладает множеством внутренних проверок безопасности и настроек прокси. Иногда более эффективным (и быстрым) оказывается использование системной библиотеки Windows WinHttp.WinHttpRequest.5.1.
Важно: Этот метод будет работать только если серверная часть 1С (или Apache в случае файловой базы) работает под управлением ОС Windows.
&НаСервереБезКонтекста
Функция ВыполнитьЗапросЧерезWinHttp(URL)
Попытка
ВебКлиент = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
// Установка тайм-аутов: Resolve, Connect, Send, Receive (в мс)
ВебКлиент.SetTimeouts(5000, 5000, 10000, 10000);
ВебКлиент.Open("POST", URL, Ложь); // Ложь - синхронный вызов
ВебКлиент.SetRequestHeader("Content-Type", "application/json");
ВебКлиент.SetRequestHeader("Accept", "application/json");
// Тело запроса
Данные = "{""test"": ""value""}";
ВебКлиент.Send(Данные);
Если ВебКлиент.Status = 200 Тогда
Возврат ВебКлиент.ResponseText;
Иначе
Возврат "Ошибка сервера: " + ВебКлиент.Status;
КонецЕсли;
Исключение
Возврат "Критическая ошибка: " + ОписаниеОшибки();
КонецПопытки;
КонецФункции
Как отмечают разработчики, использование WinHttp часто показывает лучшую производительность по сравнению со штатным HTTPСоединение, так как объект работает напрямую с системными сокетами, минуя некоторые уровни абстракции платформы 1С.
Разберем ситуацию с точки зрения системного администрирования. В файловом варианте работы через веб-сервер Apache каждый запрос занимает один поток (thread). Если одна база вызывает другую на том же сервере, она занимает один поток как "клиент" и требует еще один поток как "сервер". Если лимиты Apache настроены слишком низко, возникает взаимная блокировка.
Необходимо отредактировать файл конфигурации httpd.conf. Найдите секцию mpm_winnt_module (для Windows) и увеличьте количество потоков:
<IfModule mpm_winnt_module>
ThreadsPerChild 150
MaxConnectionsPerChild 0
</IfModule>
Параметр ThreadsPerChild определяет, сколько одновременных соединений может обрабатывать Apache. Увеличение этого значения позволяет серверу выделить свободный поток для второй базы, пока первая ожидает ответа.
Для успешного внедрения взаимодействия между базами рекомендуем придерживаться следующих шагов:
USR1CV8 или SYSTEM), имеет права на запуск сетевых соединений и доступ к каталогам обеих файловых баз.error.log в папке logs вашего Apache. Там часто фиксируется реальная причина (например, AH00161: server reached MaxRequestWorkers setting).HTTPЗапрос.УстановитьТелоИзСтроки() всегда проверяйте кодировку. Для веб-сервисов стандартом является UTF-8 без маркера BOM.Подводя итог, можно сказать, что «дружба» веб-клиента и HTTP-соединения требует внимательного отношения к сетевой инфраструктуре. Наилучшим архитектурным решением остается разнесение сервисов на разные порты или IP-адреса, а для повышения стабильности и скорости на Windows-серверах — использование объекта WinHttp.