Workaround me в 1С\MS SQL и не только, научный подход к созданию костылей -3


Нормальные герои всегда идут в обход

Айболит 66

Думаю что многие встречались с необъяснимым поведением компонентов 1С, подсистем ОС, драйверов, СУБД  которое видно в трассировке, но трассировка не отвечала на главный вопрос почему? Т.е. по документации должно работать, но не работает.

Несмотря на все более возрастающее движение за системы с открытым кодом, всегда есть что-то к чему нет исходников,  либо нет компетенций, ресурсов в них разбираться. Ну даже если Вы найдете причину в открытом коде – скажем PostgreSQL, чтобы это исправить нужны хорошие навыки и  компетенции. И все дороги получается ведут по пути Workaround (обходной путь), поскольку решение службы поддержки ждать дольше.

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

В английском закрепился термин и ему посвящена статься в Wiki , где его связывают с анти-паттерном

Workaround wiki

Надо сказать Workaround не обязательно костыль, или заплата, но он всегда несет в себе какие-то минусы – ведь мы действуем обходным путем

Термины не возникают на пустом месте – значит сложилась предыстория, приемы, методы которые нужно было как то назвать. Например названия трюков на вейкборде Ollie, Wake to wake и т.д… это ниточка за которой тянется техника, подводящие упражнения и многое другое

Умение создавать workaround жизненно важно для систем,

  1. У которых маленькие технологические окна . Например наша, где роботы работают почти круглосуточно 1с БодиПозитив   и с высокой нагрузкой.

  2. Устаревшие системы, которые сняты с поддержки

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

  4. Системы крупных вендоров, где не будет мгновенной реакции службы поддержки (Конечно Вы можете попробовать расширенную поддержку 1С Корп, но руководство будет смотреть на Вас, а не на поддержку 1С  ???? )

  5. Я надеюсь  в комментариях добавят еще интересные кейсы

Разберем методы создания Workaround на реальных историях. Предлагаемая классификация методов наверняка не полная и в комментариях к статье добавят много нового

История №1 Как MS SQL случайным образом отключал соединения 1С (актуально и сейчас)

Все началось с жалоб пользователей на ошибки сверки с Backoffice при закрытии дня. Анализ показал, что некоторые фоновые задания, применяющиеся при расчетах с горизонтальным маштабированием завершались некорректно. Надо заметить что 1С сейчас хранит историю только по 1000  последних фоновых заданий, и мы создали расширенное логгирование в конфигурации для отслеживания таких ситуаций.  Подробнее о проблеме можно посмотреть тут  Язык мой Враг мой .

В 1С проблему можно локализовать анализом тех журнала, а там заметили следующее

16:42.3540-0,SCOM,2,process=rphost,t:clientID=2352,Func='setSrcProcessName(MyDB, MyDB)'

16:42.4481-0,EXCP,2,process=rphost,p:processName= MyDB,t:clientID=2352,t:applicationName=BackgroundJob,t:connectID=14847,Exception=DataBaseException,Descr='Ошибка СУБД:

Microsoft SQL Server Native Client 11.0: TCP Provider: An existing connection was forcibly closed by the remote host.

 

HRESULT=80004005, HRESULT=80004005, SQLSrvr: SQLSTATE=08001, state=1, Severity=10, native=10054, line=0

Удивительно – но MS SQL сам отключает коннекты  «случайным образом»? Анализ логов MS SQL \Операционной системы ничего не дал, в какие то критические режимы MS SQL не входил.

Выхода было два либо копать глубже с трассировкой на уровне стека TCP и MS SQL Profiler либо задать вопрос Google – возможно он не даст прямое решение, но какую то идею

К счастью Google сразу вывел на статью Microsoft

TLS Connection forcibly closed  где была описана ошибка в TLS протоколах и Workaround для  нашей версии Windows – отключить TLS_DHE_* в групповых политиках.

В данном случае  workaround сделан по принципу

Не работает – измени окружение

Поскольку проблемные методы шифрования были убраны из политик и оставлены работающие – окружение 1С – MS SQL сервер изменилось

У кого-то возникнет вопрос – а как действовать если Google не вывел на прямой ответ?

Многие бросаются ставить все возможные патчи - ковровой бомбардировкой на ОС, SQL Server , 1С. Мне не нравится этот метод поскольку они могут привести к другим проблемам, если длительно не выдержаны и протестированы на резервном контуре\контуре тестирования. Кроме того,  в рассматриваемом случае патчи есть только для новых ОС

В рассматриваемом случае можно еще больше локализовать проблему – ведь ошибка TCP провайдера не означает что проблема на транспортном уровне модели OSI . Нужно проверять еще прикладной , представления , сеансовый. В документации по ошибке есть пример network traсe который позволяет ее выявить  и судя по всему это сделано WireShark Habr o WireShark  и придется привлечь системных адмнистраторов.

Если повезет можно быстро понять что дело на уровне шифрования TLS  , но если нет возможности заниматься анализом, можно поступить по другому.

В нашем случае ошибка регистрируется периодически для фоновых заданий при взаимодействии сервера приложений 1С и SQL сервера и вредит она фоновым заданиям

Вариант 1. А что если сделать повторный запуск фоновых заданий в 1С, если оно не доработало? В целом это нормальный вариант, который повысит выживаемость 1С в нестабильной среде при любых таких плавающих проблемах.  Такой подход называется

Не работает - Измени подсистему и ее поведение

Вариант 2 Перенастроить кластер 1С на сервер с MS SQL и включить Shared memory protocol . Радикальная смена стека протоколов поможет обойти проблему по пути  «Не работает – измени окружение». Да на нагрузка на оборудование возрастет, но зато прикладные проблемы уйдут

Сделав обходной путь можно спокойно докапываться до сути проблемы на резервном кластере.

Для крупных систем наличие резервного дублирующего контура жизненно необходимо чтобы

  • тестировать все патчи и обновления

  • воспроизводить,  исследовать, взаимодействовать со службой поддержки по таким проблемам

  • подготовить среду,  где эти проблемы не возникают (напр новая операционная система, новый набор патчей и т.д.)

История №2 Как ускорить запись в регистр сведений 1С? Почти Антипаттерн пока 1С не исправит

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

Допустим нам нужно импортировать операций по которым 6 миллионов изменений за день, а уникальных операций около миллиона в день. Изменения поступают по шине RabbitMQ.

Построим регистры СУУ_АгрегированнаяСделкаКП (Индексы по измерениям , поле Удалено, Дата)

СУУ_НеобязательныеРеквизитыДляАгрегированныхОпераций (Индексы по измерениям)

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

Но если мы захотим обновить 1000 операций , то это можно сделать только по отдельным ИдИсхСистемы - поскольку фильтр отбора по измерений 1С работает только на равенство везде т.е. получим 1000 отдельных вызовов .Записать()

Метаданные типа Документ еще хуже – документы можно записывать по одному , а не несколько в крупном DML.

Даже если эти записи распараллелены на 40 потоков – SQL сервер будет под атакой тысяч небольших DML операций со всеми вытекающимидля производительности.

Добавлю, что при обновлении нужно решать проблему правильной записи версий, чтобы версия 1 не записалась поверх версии 2

Как укрупнить DML в таких условиях если хочется остаться в рамках 1С?

Изменить свое отношение к проблеме, решай другую проблему

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

Но ведь можно ничего не обновлять, а писать сразу версии! Сделаем регистры сведений периодическими и будем писать версии (версия в стандартном поле Период )! Главное чтобы версия была одинакова и у реквизитов и операций . Поле Период по факту будет временем начала записи пакета из 1000 операций\необязательных реквизитов

Да усложнится отбор операций для последующей обработки  - ведь нам нужно отбирать последние версии операций и соединять их при необходимости с последними версиями необязательных реквизитов. Но зато мы можем организовать импорт максимально быстро в данном окружении

Анонс: Эффективное написание запросов в этом случае тема отдельной статьи

 1С и в этом случае добавляет барьеров в виде неэффективных соединений с временными таблицами ( подробно тут 1С Миссия невыполнима. Общие реквизиты разделители против временных таблиц ) но в целом задача решается, просто изменением подхода к проблеме.

Хочется еще быстрее – тогда пишите в регистр сведений напрямую минуя 1С , но это уже другая история. 

История №3 Как рабочий процесс 1С терял контекст драйвера Oracle

Дело было в 2014 году , мы активно распараллеливали импорта фоновыми заданиями задачи импорта. Появилась задача импортировать операции с базы на Oracle  в 1С, обращение к серверу Oracle шло с использованием драйвера Oracle12c, на сервере приложений. В процессе эксплуатации начали регистрироваться сбои. Текст ошибки не помню, но суть была в потере контекста для определения параметров Oracle_home, причем периодически, а не постоянно.  

Замечу, для драйверов Microsoft для Oracle ничего подобного не наблюдалось, но по разным причинам нужно было использовать родной драйвер Oracle

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

Не работает - Измени подсистему и ее поведение               

Подсистема работы с внешними источниками в 1С тогда еще была с ограниченным функционалом, поэтому использовали ADODB

Сначала была попытка соединится правильно, но если не удавалось создавали Ole вызов клиента 1С на сервере из фонового задания, и уже через Ole брали данные. Обходной вариант выглядел так (код сократил для удобочитаемости)

ADOConnection = СУУ_СоздатьОбъектАДО(ИДВызова, "ADODB.Connection");

                Если ADOConnection = Неопределено Тогда

                               Возврат Неопределено;

                КонецЕсли;

                

                ОбъектОЛЕ = Неопределено;

                

                СоединениеУстановлено = Ложь;

                // установка соединения

                Попытка

                

                               ADOConnection.Open(СтрокаСоединения);

                               СоединениеУстановлено = Истина;

                               

                Исключение

                // Ошибка

                               

                КонецПопытки;

                

                Если НЕ СоединениеУстановлено Тогда

                

                               // сюда дойдем, если при подключении через родной объект ADODB.Connection произошла ошибка

                               

                               // на ORACLE x64 + 1С x64 + Windows x64 есть ошибка - после какого-то количества успешных подключений возникает ошибка.

                               //решение проблемы не найден. есть только обход:

                               //если соединение не установилось из конкретно этой базы в серверном режиме, то нужно получить соединение

                               //из клиента 1С, который всегда x32

                               //для этого написана микро-конфа с тремя экспортными методами:

                               //ADOConnectionObj();

                               //ADOCommandObj();

                               //ADORecordsetObj();

                               //фишка - если получили Connection таким образом, то и Command нужно тоже получить из 32-х разрядного клиента,

                               //иначе будет ошибка на этом моменте: Command.ActiveConnection = ADOConnection;

                               

                               ОбъектОЛЕ = Неопределено;

                               Попытка 

                                               

                                               ОбъектОЛЕ =  Новый COMобъект("V82.Application");

                                               ОбъектОЛЕ.Visible=Ложь;

                                               ОбъектОЛЕ.Connect("File=""C:\1C\ComSrv""; Usr="""";Pwd="""";");

                                               ОбъектОЛЕ.Visible=Ложь;

                                               СоединениеОЛЕ = Истина;

                                               

                               Исключение

                                               //Сообщаем об ошибке

                                                УничтожитьОбъектАДО(ADOConnection);

                                               УничтожитьОбъектОЛЕ(ОбъектОЛЕ);

                                               

                                               Возврат Неопределено;

                               КонецПопытки;

 

Некрасиво получается, а что делать?

Не работает – убери подсистему из окружения

Более красивый вариант – создать DBLink с Oracle на MSSQL сервере, где находилась база 1С , и обращаться уже к DBlink используя только драйвера Microsoft, так в принципе можно сделать более универсальным код работы с внешними СУБД. Минус – слишком много слоев и сложный маршрут по сети (1С сервер – MS Sql сервер – Oracle сервер).

История №4  из Java

Я не эксперт в Java, но писал небольшие приложения для склеивания 1С с различными шинами, приложениями, для администрирования СУБД и т.д. Ведь когда что-то в 1С невозможно проще найти это в мире Java и интегрировать.

При попытке написать приложение с использованием JSF + Glassfish обнаружил что связка категорически не хочет работать даже с Hello word см тут

Мой наивный вопрос на StackOverflow

Я не смог найти рецептов понять причину проблемы, и пришлось решить сменой сервера приложений Glassfish на Payara. Да вот так радикально. Вообще качество  решений на Java это тема отдельной статьи. Количество конкурирующих решений размывает качество тестирования на конечных потребителях. И после этого начинаешь очень ценить порядок и предсказуемость в платформе 1С ????.

Очень интересно будет увидеть в комментариях случаи и решения не укладывающиеся в данную классификацию и другие методы создания Workaround. Присоединяйтесь к нашему телеграмм каналу t.me/Chat1CUnlimited.




Комментарии (0):