Почему долго передается массив данных с сервера на клиент в 1С и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Приветствуем вас! В процессе разработки на платформе 1С:Предприятие 8 часто возникает классическая проблема: передача относительно небольшого объема данных (например, массива из 20 000 ссылок на документы, который физически весит не более 700-800 Кб) с сервера на клиент занимает непозволительно много времени — вплоть до нескольких минут. На первый взгляд это кажется парадоксом, ведь современные сети должны передавать такой объем практически мгновенно.

В этой статье мы подробно проанализируем эту ситуацию, выявим скрытые механизмы платформы 1С, которые приводят к «зависанию» системы, и рассмотрим по шагам, как решить эту проблему раз и навсегда.

Причина 1. Неявное разыменование ссылок на клиенте (главный виновник задержек)

Когда мы передаем с сервера массив, содержащий элементы типа ДокументСсылка.ЗаказПокупателя, сама передача ссылок (которые по сути являются уникальными идентификаторами UUID) действительно происходит быстро. Проблемы начинаются тогда, когда клиентское приложение начинает работать с этим массивом на своей стороне. Любая попытка обратиться к реквизиту ссылки на клиенте приводит к катастрофическому падению производительности.

Разберем, что происходит при следующем коде на стороне клиента:


Для Каждого ЭлементИзМассива Из ПолученныйМассив Цикл
    ТекстПредставления = Строка(ЭлементИзМассива); // Неявный вызов сервера!
    Если ЭлементИзМассива.Проведен Тогда // Еще один неявный вызов сервера!
        // Выполнение логики
    КонецЕсли;
КонецЦикла;

При каждом обращении к свойству ссылки (например, Проведен, Дата, Номер) или при попытке получить строковое представление через функцию Строка(), платформа 1С выполняет синхронный неявный вызов сервера для получения этих данных из базы данных. Для 20 000 элементов это означает 20 000 отдельных сетевых запросов типа «туда-обратно». Даже при идеальном пинге локальной сети в 2 мс суммарное время ожидания составит не менее 40 секунд. Если же пользователи подключены удаленно (через VPN или медленный интернет), этот процесс легко растягивается на 5-10 минут.

Решение проблемы: Никогда не передавайте «голые» ссылки на клиент, если там планируется чтение их реквизитов или вывод представлений. Вместо этого сформируйте на сервере массив легких структур, содержащих все необходимые текстовые и числовые значения:


&НаСервереБезКонтекста
Функция ПолучитьДанныеЗаказовНаСервере()
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	ЗаказПокупателя.Ссылка КАК Ссылка,
        |	ЗаказПокупателя.Номер КАК Номер,
        |	ЗаказПокупателя.Дата КАК Дата,
        |	ЗаказПокупателя.Проведен КАК Проведен
        |ИЗ
        |	Документ.ЗаказПокупателя КАК ЗаказПокупателя";
    
    РезультатВыгрузки = Запрос.Выполнить().Выгрузить();
    
    МассивДанных = Новый Массив;
    Для Каждого Строка Из РезультатВыгрузки Цикл
        СтруктураДанных = Новый Структура;
        СтруктураДанных.Вставить("Ссылка", Строка.Ссылка);
        СтруктураДанных.Вставить("Представление", Строка(Строка.Ссылка));
        СтруктураДанных.Вставить("Номер", Строка.Номер);
        СтруктураДанных.Вставить("Дата", Строка.Дата);
        СтруктураДанных.Вставить("Проведен", Строка.Проведен);
        МассивДанных.Добавить(СтруктураДанных);
    КонецЦикла;
    
    Возврат МассивДанных;
КонецФункции

Причина 2. Накладные расходы на передачу контекста формы

Очень часто разработчики вызывают серверные методы формы, используя стандартную директиву компиляции &НаСервере. Выясним, почему это приводит к сильным задержкам.

При вызове контекстной серверной процедуры платформа вынуждена сериализовать и передать на сервер абсолютно весь контекст текущей формы: значения всех реквизитов, данные табличных частей, состояние элементов управления и прочее. После выполнения процедуры весь этот массив информации упаковывается обратно и отправляется на клиент. Если на форме отображается тяжелая таблица с тысячами строк, то даже простой возврат булевого значения или небольшого массива через контекстный метод вызовет огромный сетевой трафик и нагрузку на процессор.

Решение проблемы: Всегда используйте директиву &НаСервереБезКонтекста для функций, которые просто получают данные из базы и возвращают их на клиент. Это полностью исключает накладные расходы на передачу контекста формы, так как на сервер передаются только параметры, явно указанные в скобках вызова.

Причина 3. Тяжелая XML/XDTO-сериализация стандартных коллекций

При передаче сложных объектов, таких как ТаблицаЗначений, ДеревоЗначений или даже больших массивов структур, платформа осуществляет их сериализацию в формат XML (через внутренние механизмы XDTO). Процесс разбора XML-пакетов на клиенте является однопоточным и сильно нагружает центральный процессор клиентской машины.

Проанализируем две альтернативные стратегии оптимизации сериализации данных:

  1. Использование формата JSON. Текстовый формат JSON гораздо лаконичнее XML, а сериализация и десериализация в 1С для него работают в разы быстрее. Мы можем преобразовать массив структур в JSON-строку на сервере с помощью объекта ЗаписатьJSON и быстро восстановить его на клиенте через ПрочитатьJSON.
  2. Передача через Временное хранилище. Если массив данных нужен на клиенте только для того, чтобы передать его в другую форму или в последующий серверный вызов, физически передавать его на клиент вообще не имеет смысла. Поместите его во временное хранилище с помощью функции ПоместитьВоВременноеХранилище, а на клиент верните легкую строку-адрес (UUID).

Посмотрим на пример эффективного использования временного хранилища:


&НаСервереБезКонтекста
Функция ПоместитьМассивВХранилище()
    МассивСсылок = Новый Массив; // Допустим, здесь 20 000 ссылок
    // Код заполнения массива...
    
    АдресХранилища = ПоместитьВоВременноеХранилище(МассивСсылок, Новый УникальныйИдентификатор);
    Возврат АдресХранилища; // Возвращаем только короткую строку-адрес
КонецФункции

Причина 4. Проблемы сетевого стыка между Linux-сервером и Windows-клиентом

В гетерогенных сетях, где сервер 1С функционирует под управлением ОС Linux, а клиенты работают на ОС Windows, нередко возникают специфические сетевые задержки при передаче больших пакетов данных.

Разберем основные системные проблемы и способы их устранения:

  1. Обратное разрешение имен (Reverse DNS). При получении запроса от клиента Linux-сервер пытается разрешить его IP-адрес в доменное имя. Если DNS-сервер в сети настроен некорректно или имеет медленный отклик, этот PTR-запрос зависает по таймауту на каждом сетевом пакете. Решением является жесткое прописывание IP-адресов рабочих станций в файл /etc/hosts на сервере 1С или отключение DNS-резолва в настройках сети Linux.
  2. Функция автоподстройки TCP-окна в Windows. Встроенная функция Windows Receive Window Auto-Tuning иногда некорректно взаимодействует со стеком TCP/IP операционных систем Linux, искусственно занижая пропускную способность сетевого канала. Для исправления этой проблемы на клиентских машинах администраторы отключают автоподстройку через командную строку от имени администратора:

netsh int tcp set global autotuninglevel=disabled

Причина 5. Блокировка и сканирование сетевого трафика антивирусным ПО

При передаче больших объемов данных между сервером и клиентом 1С генерирует интенсивный поток XML/XDTO данных через сетевые порты рабочих процессов (диапазон 1540-1591). Многие современные антивирусные системы со встроенными сетевыми экранами (Firewall) и веб-фильтрами пытаются перехватить этот поток для анализа «на лету».

Для больших пакетов данных такой анализ создает колоссальную задержку, так как антивирусу требуется накопить пакет в буфере, распаковать его и проверить. Решением является добавление процессов 1С (1cv8.exe, 1cv8c.exe) и используемых сетевых портов в список исключений сканирования вашего антивирусного программного обеспечения.

Подводя итоги, отметим, что скорость клиент-серверного взаимодействия в 1С зависит не столько от физического объема данных, сколько от выбранной архитектуры решения. Минимизируйте контекстные вызовы, избавляйтесь от неявного разыменования ссылок на клиенте и используйте временное хранилище — это позволит вашей системе работать максимально быстро и отзывчиво!

← На главную