Alexander Speshilov (speshuric) wrote,
Alexander Speshilov
speshuric

Category:

про работу.

Присказка


Я давно тружусь "прикладным программистом для системы 1С:Предприятие". С точки зрения маркетинга и своевременности на рынке очень удачная система и, что характерно, в целом старается оставаться. С технической/технологической - не безупречно, но глядя на остальные какашки отечественного рынка, просто гордость за 1С берёт.
Хорошая система, универсальная, да вот есть и у неё области для которых она не пригодна. Использовать её в этих областях можно, но это будет дорого и ненадёжно. Вот возьмём, например, высоконагруженные системы: биллинг, он-лайн трейдинг на бирже, системы с большим количеством пользователей и операций пользователей. Ситуация чем-то напоминает "культ карго". Вроде и СУБД приличные, кросс-платформенность, что аж обзавидоваться, объектная модель относительно стройная (кто не согласен - могу аргументированно посравнивать с Аксессом тем же), диаграмки бизнес-процессов появились, внедренцы нынче не в трамвае в футболке приезжают, а на иномарках в пинжачках. Красота. А вот уй. Не предназначена. Программисты-разработчики её не писали для такого, и уши этих решений будут постоянно торчать.
Вот тут обычно из слушателей-собеседников выкристаллизовываются 2 большие группы. Одни скажут: "Вот ведь говнецо ваша 1С, там даже язык программирования на русском", другие: "Да кто ты такой так осквернять святыню. На 1С можно написать искусственный разум, и это уже сделал Сергей Нуралиев, но пока не пришло время явить Его миру". Вот с этими группами я прямо здесь могу распрощаться. Первые уходят искать достойного конкурента 1С, вторые идут искать информацию о том как 1С в оперативной памяти числа хранит, и сравнивают с другими реализациями. А я отмечу лишь несколько моментов, что мне мешает в создании высоконагруженных систем в 1С. Перечислю далеко не всё, скорее то, обо что реально спотыкаемся. Есть куча мелких проблем, но они скорее жужжат, но не кусают. Типа таких: неполное использование возможностей СУБД (простите, кросплатформенность), прожорливость по ресурсам (покупайте железку, на лицензиях сэкономили), медленный интерпретатор (куда торопиться - один фиг на выборке из БД всё просадится), куча блокировок при работе с БД, невозможность создавать произвольные индексы и еще куча обглоданных и сто раз описанных проблем. К тому же это и не проблемы, а так - чтобы жизнь интереснее была.
  1. Реально выбивает отсутствие типа времени, точнее, чем секунда. Не зря 1С - 1 с. Для бухгалтерской программы в большинстве случаев откровенно пофигу на доли секунд, но если у вас больше 100000 событий в день, то их даже нельзя раскидать на оси времени в достоверной последовательности не прибегая к костылям. Что делать если система должна хранить информацию о более чем миллионе событий (документов) в день, да еще и не раскиданные равномерно по суткам - решительно не понятно.
  2. Очень напрягает медленная работа с БД на изменение. По сути update'ов и insert'ов работающих с множеством записей вообще нет, а delete только для очень частного случая (и то - кто из программистов 1С не сносил регистр сведений целиком из-за этого случая? :)). Скорость вставки, если не прибегать к мегаизвратам для записей в 100-200 байт не выходит за 500-1000 записей в секунду из одного клиентского соединения. Для большинства типовых загрузок это вообще 1-50 документов в секунду. Те же данные банальным bulk insert вставляются 10000-30000 записей/сек на той же железке.

  3. Бедный язык запросов. Он похож на обычный SQL, но в нём нет нескольких важных особенностей. Нет windowed аггрегатных функций, нет рекурсивных запросов, нет подзапросов для выборки одиночных значений в части между SELECT и FROM (как нет и OUTER APPLY, которым это можно заменить), нет банального EXISTS.
  4. Самое важное. 1С писали не для этого. Продеменстрирую на паре примеров.
На новый 2011 год мы перешли с древней, как говно мамонта версии 8.0.12 (дадада, той самой, в которой еще не было администраторов сервера), на 8.1.15. Релиз 8.1.15 является последним и наиболее стабильным релизом версии 1С 8.1. Последующие были уже 8.2, да и по стабильности там пока еще вопросов многовато (и это за год, когда система уже якобы вовсе и не бета!). В целом переход был гладким (насколько он может быть гладким для совершенно нетиповой базы нашего размера). Переходили максимально аккуратно и поэтому большинство решений использовавшиеся в 8.0 продолжают (временно) использоваться в 8.1, т.е. наш код был к концу декабря так, чтобы он одинаково работал в 1С 8.0 и 1С 8.1. Полученную информационную систему конечно тестировали (и функционально, и нагрузочно, и пользовательские части и серверные), но видимо недостаточно. Уже в первые рабочие дни мы словили 2 мощные проблемы.

сказка


Глюк первый. При нормальной работе пользователй сервер приложения вдруг отправляется в мир иной, оставив клиентские сессии сиротинушками, а незафиксированные транзакции откатывает, служба рестартует. После второго "Ой" от сервера я настроил технологический журнал на сервере и уже на третий за день инцидент выяснилось, что падает при получении списка активных польователей (а надо сказать, что это действие у нас происходило ОЧЕНЬ часто). Ну что, к вечеру 11.01 с кучей матов был создан костыль, который максимально исключал получение этого списка. 12.01 вечером выяснилось, что этого недостаточно. 13.01 были убраны все получения списка программные и всем, кто имел доступ к получению списка интерактивно было устно запрещено его получать. В пятницу я подготовил скриптец, который получает этот список в цикле, но не смог его тестировать даже на разработческих серверах (уж очень весело всё падало). Дожили до выходных. Начали гонять тесты (на тестовых и боевой системе), выяснили:
  1. Падает на активной работе служебных пользователей (которые часто подключаются/отключаются)

  2. Падает на основном сервере и на разработческом сервере, но не падает на старом разработческом сервере. На серверах подготовки отчетов проверить было нельзя, поэтому там не проверяли.
Копаем дальше. Подозреваем что всё дело в кривой установке (у остальных же не падает) или битности приложения (есть 2 версии сервера 32 и 64 бит). Вызываем духа админов. Не помогает. Тратим время на эти проверки. Не помогает. Танцуем с бубном. Не помогает. Пытаемся найти того служебного пользователя, во время которого падает сервер. Выясняется, что во время работы любого служебного пользователя 1С может упасть, а обычные пользователи на это не влияют. Еще примерно через час выясняем, что проблема в том, что служебные пользователи прекращают сеанс вызовом метода "ПрекратитьРаботуСистемы()". Вообще у 1С есть 2 метода для завершения сеанса: "ЗавершитьРаботуСистемы()" и "ПрекратитьРаботуСистемы()". Первый боле "мягкий", а второй - безусловный. Смоделировали. Да, именно так: в некоторых случаях когда в одном клиентском сеансе выполняется "ПрекратитьРаботуСистемы()", а в другом выполняется "ПолучитьСоединенияИнформационнойБазы()" система падает. А на старом сервере она не падала, потому что он слишком медленный (недостаточная интенсивность операций). Поменяли везде "ПрекратитьРаботуСистемы()" на "ЗавершитьРаботуСистемы()" и живём теперь. А служебных пользователей активно переносим в серверные фоновые и регламентные задания (т.е. теперь будет не вызов специальным клиентом действий, а сразу на сервере действия).
Но это была разминка. Сама ошибка достаточно легко локализовалась, данные целы, выявляется и исправляется проблема быстро (все падают, переподключаются и всё). А вот вторая проблемка до сих пор не факт что решена (хоть и не происходила уже 2 дня). Проблема такая: иногда, без видимых причин один из клиентов (опять же обычно служебных, мать их, пользователей) говорит: 3902! "Тhe COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION." Дело осложняется следующими нюансами: программист 1С не напрямую работает с СУБД и такую ошибку вызвать не может (платформа ему сама насчитает коммиты и выдаст своё сообщение, которое хотя бы отловить в коде не проблема), сеанс клиента тупо висит с модальным диалоговым окном об ошибке и эту ошибку не отловить в коде (учитывая, что это периодически запускаемое задание - крайне обидно и сложно отловить). Но и это не самое печальное. Печально то, что в технологическом журнале сервера и клиента 1С (это грубо говоря полный лог действий системы) нет очевидных причин и одинаковых ситуаций для падения. И самое противное, что Менделеев всё-таки был прав. Ежели где-то коммитов излишки, то, блин где-то их будет недостача. И эта недостача была в одном из соседних коннектов.
С точки зрения целостности данных ситуация ужасная:
  1. В том соединении где была ошибка - фиг знает были ли команды DML (изменения данных), которые должны быть в транзакции одиночными. Или хотя бы все ли они были вне транзакции и выполнены.
  2. Во стором соединении данные откатываются. Это бы не было страшным, если бы система не считала эту транзакцию закоммиченной! Пользователь (или робот) честно думал, что транзакция зафиксирована и послал, например, уведомление в другую систему о загрузке данных. А потом его труды пропадают.
  3. Пока второе соединение висит "без коммита" у него открыта транзакцияи скапливается дикое количество блокировок.
Пипец! Пришлось настроить оповещение от MS SQL об ошибке 3902 на СМС. При возниконовении ошибки приходится останавливать всю работу системы, проверять что делалось в отменённых соединениях (по ТЖ - технологическому журналу и по трассе событий SQL:Batch Complete). Читать ТЖ достаточно проблемно. Это набор текстовых файлов, каждый из которых отражает работу одного процесса за один час и даже не в самом полном режиме у нас занимает 1-3 ГБ. 1-3 ГБ за час. Парсера у нас пока нет (он входит в диагностический пакет 1С, котрый будет куплен, наверное в марте). Формат такой, что в SQL его запихнуть проблематично. Большинство редакторов текста с такими файлами не дружат. В этой проблеме приходится разбираться на фоне других шерховатостей перехода и на фоне вполне понянтного недовольства начальства и заказчиков.
Выяснилось, что проблема возникает так: при большом количестве коротких транзакций иногда бывает что одно соединение с БД из пула выдаётся двум клиентским соединениям. Одно уже к этому времени сделало BEGIN TRAN, а второе только запрашивает соединение. При этом у первому соединению отдаётся новое соединение. Порог при котором это всё начинает себя так вести - около 1000 транзакций в секунду с одного соединения.
У нас такое количество транзакций происходит при чтении изменений из плана обмена "ВыборкаИзменений = УзелПланаОбмена.ВыбратьИзменения();" и потом "Объект = ВыборкаИзменений.Получить();" в цикле. При этом каждое ВыборкаИзменений.Получить() является отдельной транзакцией. Ну плюс на самом деле мы там несколько небольших прикладных ошибок нашли, но факт остаётся. Залечили достаточно просто: каждые N ВыборкаИзменений.Получить() и операций выгрузки данных делаются в единой транзакции, так что количество транзакций резко снизилось (фактически в 2*N раз). Уже несколько дней я не получаю (тьфу-тьфу) страшную СМС. Потихоньку отслеживаем все корявые места в коде, где может быть много транзакций и пытаемся это дело оптимизировать. На выходных попробую репру для 8.2 сделать. Если будет валить 8.2 - пошлю в 1С. Если не будет (первую багу, кста, исправили или уменьшили вероятность до ненаблюдаемой) - придётся смириться, потому что на 8.2 мы раньше июне не мигрируем.

Мораль басни


Помню, как-то раз я удивился, правильно ответив (не угадав!) Денису Анатоличу (Анатолич, привет!) на пост типа "угадайте где бага". Прочитал пост в сортире с телефона, ответил с телефона. С++ (о котором был вопрос), конечно, немного знаю, но не зубр (хотя небольшие внешние компоненты и не проблема написать). Потом на самом деле оглянулся, что ему в чем-то проще. У него хотя бы исходный текст его мамонта под рукой есть (ну или был на тот момент). У меня только ибучая интуиция - где же программисты платформы чаще всего ошибки совершают. Люди вообще и программисты в частности делают очень много ошибок. Иногда мне кажется, что программисты вообще делают только ошибки, а работающий код - результат какого-то нематериального процесса, в котором программисты лишь выступают мутагенным фактором. Так вот этой мутагенности в программистах платформы явно выше в тех областях, которые качаются больших нагрузок. Поэтому если будете делать высоконагруженную систему на 1С - скорректируйте бюджет на пару зарплат таких решателей проблем как я (не-не-не, не почасовка, оклад, и не одного как я, а двоих), не забывая, что эта зарплата будет на некоторый процент выше большинства остальных разработчиков. Прибавьте риски (простой системы и потеря данных). Что? Многовато? Ну это по сравнению с чем. Если у вас есть готовый движок для биллинговых систем, то да, а если вы думаете, что ваши программисты могут написать лучше, чем 1С, то сомневаюсь (если конечно у вас нет хотя бы пары десятков упомянутых Анатоличей, но, как гововил товарищ Сухов: "Это вряд ли"), а если думаете, что лучше да еще и дешевле, то срочно бросайте те наркотики, которые употребляете.
Subscribe

  • Странная штука powershell...

    Странная штука powershell... Простой скрипт: $start = get-date for($i=1; $i -le 1000000; $i++){} $end = get-date ($end-$start).TotalMilliseconds #…

  • про Linux

    С IE на оперу я перелез, когда мне понадобилось сильно экономить трафик. Других достоинств у оперы нет и не было. Как появилась возможность - перелез…

  • Об эффективности отечественной государственной системы

    Только Факты: 1. Сегодня курс доллара 1$ = 28.223 (по данным rbc.ru) 2. По данным BBC: Соединенные Штаты уже потратили на участие в военной и…

  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 49 comments

  • Странная штука powershell...

    Странная штука powershell... Простой скрипт: $start = get-date for($i=1; $i -le 1000000; $i++){} $end = get-date ($end-$start).TotalMilliseconds #…

  • про Linux

    С IE на оперу я перелез, когда мне понадобилось сильно экономить трафик. Других достоинств у оперы нет и не было. Как появилась возможность - перелез…

  • Об эффективности отечественной государственной системы

    Только Факты: 1. Сегодня курс доллара 1$ = 28.223 (по данным rbc.ru) 2. По данным BBC: Соединенные Штаты уже потратили на участие в военной и…