Имя: Пароль:
1C
1С v8
Где хранить HTTPСоединение?
0 Bobby McFerrin
 
03.08.21
12:39
Привет всем.
Есть обработка для отправки/получения xml файлов по SOAP. Подключение происходит через объект HTTPСоединение. Архитектура решения кривовата, HTTPСоединение создаем каждый раз когда нужно что-то отправить или получить. А на стороне сервиса стоит ограничение: не более 10 подключений по одному IP, соединение живет 30 секунд. В итоге когда запустили обработку в компании с 100 рабочими местами и единым IP адресом часть пользователей не смогла подключиться. Хочу избежать переписывания кода, не комильфо таскать объект соединения между процедурами. Закрыть соединение, насколько я понял, тоже нельзя. Появилась идея хранить созданное соединение в параметре сеанса и обращаться к нему при необходимости подключения. Если параметр еще не инициализирован – создавать соединение. Если время соединения вышло – также создавать. Один момент. Какой тип данных нужен для хранения объекта типа HTTPСоединение?
1 ДенисЧ
 
03.08.21
12:41
Напиши микросервис на GO, который будет держать соединение и отдавать JSON по запросу от клиентов.
2 acht
 
03.08.21
12:44
(0) Не вдаваясь в бредовость твоей идеи, мутабльность и сериализацию:

> не более 10 подключений по одному IP
...
> 100 рабочими местами и единым IP адресом

А теперь все 100 подключений начнут долбится с гарантировано одного ip адреса сервера. Догадайся о результате.
3 Адинэснег
 
03.08.21
12:45
прокси
4 arsik
 
гуру
03.08.21
12:47
(2) А что такого. Соединений то до 10 открыть можно и держать открытыми через (1). Нормально должно работать.
(3) Ну соединение то будет каждый раз разное
5 Галахад
 
гуру
03.08.21
12:49
(0) Сделай очередь. Пускай все централизовано ходят через 10 соединений.
6 oleg_km
 
03.08.21
12:54
(4) Тебе подсказали решение - сделай промежуточный сервис, который будет обрабатывать очередь сообщений. Можешь его сделать в фоновом задании. Т.е. в фоновом задании условно бесконечный цикл, который управляет переподключением и считывает допустим регистр сведений, в который сеансы кладут задания. Если сеансам нужны ответы, то нужно еще организовать ожидание ответа, но это тоже реализуемо, в конце концов цикл на клиентском сеансе
7 arsik
 
гуру
03.08.21
12:57
(6) Я не ТС, я поделился своим мнением
8 oleg_km
 
03.08.21
13:15
(7) Я не туда нажал
9 fisher
 
03.08.21
14:03
(0) Сервис ваш или сторонний?
10 fisher
 
03.08.21
14:05
Если сторонний, то скорее всего сабжевое ограничение ты обойти не сможешь.
11 fisher
 
03.08.21
14:07
Ибо там скорее всего ограничение тупо на количество запросов в единицу времени, а не на соединения.
12 BaZZiL
 
03.08.21
14:42
(0) Объект 1С HTTPСОединение хранящийся в переменной, с конкретным http сеансом на http сервере никак не связано. Когда соединение обращается на сервер, оно может либо попасть в существующий сеанс (в пул), либо создать новый. Чтобы увязать соединения и сеансы, надо на сервере отслеживать соединения по кукам.
Так что можно спокойно быдлокодить вызов HTTPСоединения везде подряд. Созданием какого-то "особого" HTTPСоединения в виде како-то там глобальной переменной никак не повлиять на количество сеансов с сервером.

Надеюсь, что не ересь написал)
13 ДенисЧ
 
03.08.21
14:47
(12) "Надеюсь"
Зря.
14 fisher
 
03.08.21
17:24
(13) Почему? ИМХО, суть верна. Одинэсное HTTPСоединение с точки зрения веб-сервера никакими соединениями не управляет. Поэтому я выше и написал, что если сервер чужой то фиг они что обойти смогут.
15 oleg_km
 
03.08.21
17:37
(14) Может это стоит хотя бы проверить на фиддлере прежде чем так безаппеляционно утверждать? Может сервер создает куки, а HTTPСоединение их автоматически добавляет в очередные запросы? Это описано в документации или вы анализировали поведение 1С? Если нет, тогда как можно делать такие заявления?
16 fisher
 
03.08.21
17:45
(15) Допустим куки. С точки зрения веб-сервера куки = соединения? И в разрезе них настроены ограничения?
17 PLUT
 
03.08.21
17:52
18 PLUT
 
03.08.21
17:54
+(17) https://its.1c.ru/db/intgr83#content:82:hdoc

про ручник: (да простят меня 1С за копипасту?)

Ручное управление сеансами
Стратегия ручного управления сеансами подразумевает, что клиент интернет-сервиса самостоятельно управляет количеством сеансов и временем их жизни. Эта стратегия лучше подходит для высокоинтегрированных систем в рамках одной организации. Разработчик может реализовать собственный алгоритм, который будет управлять временем жизни сеансов и их количеством.

В качестве управляющего элемента выступает заголовок HTTP-запроса IBSession. Этот заголовок может принимать два значения:

start – в этом случае система «1С:Предприятие» создает новый сеанс, выполняет аутентификацию, устанавливает разделители, выполняются все необходимые обработчики событий. Если система не может создать новый сеанс, то клиент получит ошибку 406 «Not Acceptable». Если создание сеанса выполнено успешно, в HTTP-ответ помещается директива установки cookie IBsession с идентификатором созданного сеанса: Set-Cookie: IBsession<=ID сеанса>.
При необходимости использовать ранее созданный сеанс необходимо в HTTP-запросе к системе «1С:Предприятие» указать идентификатор ранее созданного сеанса в заголовке: Cookie: IBsession<=ID сеанса>. Если в запросе указывается идентификатор сеанса, который ранее не создавался или был завершен, клиент получает ошибку 400 «Bad Request».
19 acht
 
03.08.21
17:58
(15) > Может сервер создает куки, а HTTPСоединение их автоматически добавляет в очередные запросы?

Фигасе у тебя фантазия.
20 acht
 
03.08.21
17:59
(18) Это описывается поведение системы, когда 1С является сервером.
21 fisher
 
03.08.21
18:04
(17) Читал, конечно. Во-первых это касается 1С-сервера, во-вторых управления сеансами 1С, а не "http-соединениями". С точки зрения протокола http никаких соединений не существует. Явного управления tcp-соединениями в http тоже нет.
22 acht
 
03.08.21
18:07
(21) > Явного управления tcp-соединениями в http тоже нет.
Чойта?

Connection: keep-alive
Connection: close

В HTTP/2 запрещены =)
23 fisher
 
04.08.21
09:29
(22) По дефолту все запросы по http 1.1 идут в keep-alive. Это всего лишь рекомендация веб-серверу ненадолго придержать закрытие соединения. Период этого "ненадолго" настраивается на веб-сервере. Пишут что для Apache 2.2 по дефолту 5 секунд. Я бы постеснялся называть это "явным управлением tcp-соединениями".
Но я тут подумал. Если в сабжевом сервере время жизни tcp-соединений настроено на 30 секунд, а запрос через новое HTTPСоединение гарантированно открывает новое tcp-соединение (деталей я не нашел, но у http-клиента есть такая возможность) и ограничение на сервере именно на количество одновременных tcp-соединений - тогда я неправ. Тогда переиспользование HTTPСоединение действительно увеличит пропускную способность.
24 ptiz
 
04.08.21
09:38
(0) Вряд ли сторонний сервер в курсе про объект 1С HTTPСоединение. Делай справочник "ТекущиеСоединенияСВнешнимСервером". 10 элементов. При создании нового элемента HTTPСоединение - блокируй один из элементов методом Заблокировать() (можно хоть все 10 перебирать, лишь бы захватить). Если не удалось - жди (если удалось - можно фиксировать время начала). По окончании работы - отпускай (можно фиксировать время отпускания для отсчета 30 секунд). Тогда 100 сеансов гарантировано не смогут создать более 10 штук http-соединений.
25 Смотрящий
 
04.08.21
09:39
(0) "Хочу избежать переписывания кода, не комильфо таскать объект соединения между процедурами"
Придется переписать архитектуру
Почему, кстате, некомильфо ?
26 fisher
 
04.08.21
09:47
Если вернуться к сабжевой задаче, то в (6) рабочий вариант.
Другого способа переиспользовать HTTPСоединение между разными сеансами я не знаю.
27 fisher
 
04.08.21
09:52
Для переиспользования в рамках одного сеанса достаточно получать HTTPСоединение через функцию модуля с повторным использованием возвращаемых значений.
28 ДенисЧ
 
04.08.21
09:54
(27) А в рамках 100 сеансов по изначальной постановке вопроса?
29 fisher
 
04.08.21
10:03
(28) Тогда (26). И еще параллелить на несколько потоков с координатором :) Короче, делать собственный обслуживаемый пул HTTPСоединение. Но тоже такое себе. Придется или крутить бесконечные циклы утилизируя ядра процессора или использовать паузы что добавит лагов в запросы. Внешняя приблуда при таких раскладах более привлекательно выглядит. Как ты и советовал в (1)
30 fisher
 
04.08.21
10:08
Но возможно что и переиспользование в рамках сеанса сгладит проблему в достаточной степени. Это будет выход малой кровью.
Затыки ведь будут только когда в течение 30 секунд более 10 человек одновременно попытаются сделать запрос.
31 fisher
 
04.08.21
10:16
Только если через модуль с повторным использованием возвращаемых значений делать, то надо предусмотреть ситуацию когда функция вернет Неопределено (если кэш возвращаемых значений сериализуется).
Это несложно обойти. Можно обернуть вызов в другую функцию, которая в случае возврата будет делать повторный вызов с уникальным параметром. То есть можно например в параметр сеанса писать гуид и вызывать функцию создания соединения с этим дополнительным параметром. Если вернуло Неопределено, то генерить новый гуид в этом параметре сеанса и вызывать функцию с ним. Ну а функция-обертка будет вызываться прозрачно из обычного модуля.
32 Bobby McFerrin
 
05.08.21
10:32
Спасибо всем за ответы. GO не знаю, так что решил передавать HTTPСоединение с формы в рамках одного сеанса с пересозданием соединения при ошибке в работе с ним. Это значит, что одновременно смогут обмениваться не более 10 человек из 100. Решение не идеально, но гораздо лучше чем было до этого. Тем более, как я полагаю, у клиента не все 100 сотрудников одновременно работают с обменом.
P.S. скорость передачи/получения файлов тоже возросла. Профит.
33 Сергиус
 
05.08.21
14:04
(0)Если фирма крупная(а 100 человек это явно не ларёк), то с подобными ограничениями(не более 10 на один ИП) стараются бороться сначала со своей стороны - либо берут сколько надо внешних IP и распределяют юзеров между ними. Либо договариваются с тем сервисом об особых условиях работы. Но вы пошли именно по "ларёчному" пути решения..
34 fisher
 
05.08.21
14:14
(33) "Ларечность" - какой интересный и многозначный термин.
Лично для меня ларечность - это как раз когда "берут сколько надо внешних IP и распределяют юзеров между ними".
А ТС просто оптимизировал неоптимальный код.
35 Bobby McFerrin
 
11.08.21
18:21
(1) Товарищи, понял всю бредовость своей затеи. Работало только на обычных формах и в файловой базе. Объект HTTPСоединение, FTPСоединение не передается между сервером и клиентом. Я GO не знаю, с джавой знаком немного. Написал сегодня программку, которая открывает сокет на 8189 порту, методы для подключения к FTP и работе с соединением. Дальше застрял, не понимаю, как это со стороны 1С должно выглядеть?
36 Garykom
 
гуру
11.08.21
18:23
(35) 1. Находишь $
2. Нанимаешь программиста
37 arsik
 
гуру
11.08.21
19:40
(35) Тебе же объяснили, что в HTTP нет как такового коннекта который можно хранить или поддерживать.
Просто уточни у другой стороны, что может послужить идентификацией коннекта. Куки какие или может что то в заголовке можно передать.