Microsoft Workflow - антімаркетінг

    Привіт, Хабр.
 
Я думаю, багато хто з вас чули про таку технологію — Microsoft Workflow . Вона досить непогано розкручена, є пости на Хабре , є книги англійською і російською . Та й Microsoft публікує красиві картинки .
 
Суть технології в тому, що програмісти створюють API, а бізнес аналітик вже сам створює бізнес процес. Без посередників.
Наприклад, клієнт запросив ось такий бізнес процес:
 
 image
 
І далі бізнес-аналітик саме його і малює. Програмістам варто лише реалізувати процедури Accept, Reject і інші схожі кубики. Круто, да?
Мені не особливо пощастило в тому, що я чув про цю технологію тільки з книжок і з маркетингових видань. Ну і звичайно з презентацій виду «Ми подивилися на MS WF півроку тому, вже місяць трохи використовуємо — політ нормальний!». Я ж працюю з продуктом, в якому Workflow впроваджена вже 6 років (сам я з ним працював всього пару років), який має досить високе навантаження, а тому хотів би показати основні підстави і засідки цієї бібліотеки. Я сподіваюся, пост допоможе уникнути тих же граблів, на які наступали ми.
 
 
 
Як воно працює?
Ідея вкрай проста: програміст створює кубики — Activity. Кожна Activity може мати параметри. Наприклад, можна створити RejectActivity cо властивістю User. Найчастіше це означатиме, що Reject відбуватиметься для цього User'а. Кожна Activity, по суті, має зовнішнє подання (тобто те, як її побачить бізнес-аналітик) і реалізацію. До речі, тут ми відразу отримуємо засідку # 1: це один і той же клас. Ну тобто наш красивий дизайнер повинен лінкуватися на реалізацію. Але це вирішується вкрай просто за допомогою IoC, тому назвемо це лише розминкою.
Коли бізнес-аналітик зробив дизайн (тобто намалював купу activity, з'єднав їх стрілочками), його можна зберегти як Xaml подання. Яке зможе завантажити Microsoft Workflow Runtime і почати виконувати.
На деяких Activity можна зробити паузу (наприклад, Delay Activity). У цьому випадку робочий стан серіалізуются в базу. Ну і через певний час (як ми самі вказали) наш робочий процес знову прокинеться і піде далі. Для збереження нам буде потрібно база або свій написаний сохранятель . Все круто, так?
 
 
Подстава з сериализацией
Як Ви зрозуміли з тексту вище, іноді бізнес-процес слід ставити на паузу. Типовий приклад: ми чекаємо відповіді від користувача (тобто використовуємо Event Activity). У цьому випадку відбувається звичайна сериализация (xml сериализация для Workflow 4.0 +, бінарна для більш старих версій). Я думаю, читачі відразу зрозуміли, що тут дуже легко зберегти зайве або ж трохи помилитися при збереженні в релізі А, а завантаженні в релізі Б. Типовий приклад з Workflow 3.0 — Ви підписалися на Event за допомогою Лямби / анонімного методу. Ну і, якщо ви знаєте, тим самим Ви створили нове поле класу, яке зберігається в базу. І у вас впаде завантаження, так як впаде десеріалізацію. Звідси, велику раду: Весь робочий код повинен бути строго винесений за межі ваших Activity. Всі поля повинні зберігатися небудь подалі від Workflow. У Activity зберігаємо самий мінімум і найпростіші типи. Нехай краще постраждає внутрішній дизайн, ніж стабільність .
Насправді, підставі тут не закінчилася. Саме класне починається тоді, коли треба поміняти набір полів. Наприклад, в нашу RejectActivity з прикладу знадобитися додати Reason. І ось тут код повинен бути готовий до того, що стара RejectActivity не містить цього поля. Для Workflow 4.0 + можна ще поміняти серіалізовані уявлення в базі, а от для Workflow 3.0 такий спосіб не завжди підійде (так як зберігається стислий бінарне подання), тому швидко все це не оновити.
 
 
Засідка з продуктивністю
Насправді, у Microsoft Workflow ціла серія недоробок. Причому, проблеми стосуються як одиничного виконання (тобто ряд операцій зроблений не ефективно), так і розподілу навантаження. Однак, про все по порядку.
 
 
Коли слід зберігатися?
Уявімо, у нас йде бізнес процес, в якому є нульові очікування. Не важливо, як вони вийшли. Важливо те, що вони є. Workflow трактує будь очікування як відмінний привід зберегтися, ну тобто зробити сериализацию, а потім завантажити знову нашу роботу (правда, не зовсім відразу, але не важливо). Природно, на час реакції це позначається самим несприятливим чином. Звідси порада: використовуйте Delay Activity якомога рідше, а ще краще — у зв'язці з If Activity, яка перевірить, що чекати, власне, і не треба . Інший неприємний момент пов'язаний з тим, що якщо Ви сказали «чекати 5 діб», то простими способами Ви не примусите Workflow-таки не чекати нічого, якщо наш instance вже в базі. Більш того, якщо Workflow Runtime завантажить вашу роботу в пам'ять, і побачить, що чекати слід ще купу часу то вона, як не дивно, просто залишить її в пам'яті. І буде чекати купу часу. Звідси, ще порада: через подібні проблеми не використовуйте довге очікування. Краще всього використовувати багато коротких або ж прокидатися за зовнішнього Event'а, а вже Ваш зовнішній сервіс розбудить процес коли треба .
 
 
Розподілене виконання
Якщо вірити тим же статтям від Microsoft, Workflow прекрасно вміє розподіляти роботу. Ну тобто Ви можете мати кілька незалежних серверів, кожен з яких буде брати трохи завдань, виконувати їх, брати наступні і так далі. У цьому є тільки один недолік: це вигадка. Вся справа в тому, що розподілена реалізація Workflow — це вкрай дивне виріб. Воно працює за наступним алгоритмом:
 
     
  1. Взяти з бази ВСЕ не заблоковані робочі процеси, які зараз можуть виконатися І поставити їм блокування на п'ять хвилин
  2.  
  3. Через дві хвилини: повторити пункт 1
  4.  
Так, числа 2 і 5 можна поміняти. Важливо інше: найперший везунчик забере взагалі всю роботу з бази. До речі, через дві хвилини він знову вичистить базу, навіть якщо йому є, чим зайнятися. Якщо він не вкладеться за п'ять хвилин для якого-небудь робочого процесу, то тут відбудеться дивна штука: він таки виконає робочий процес (викличе все WCF з'єднання тощо), спробує зберегти базу даних, але у нього нічого не вийде ( блокування-то нету!). У підсумку в пам'яті цього Workflow Runtime тепер уже назавжди залишиться цей ламаний об'єкт. І він не вийде з неї добровільно доти, поки Ви фізично не зупините процес. Workflow Runtime НЕ буде сам зупинятися, зробити він вже нічого не зможе. Чудова реалізація. Більш красивий сценарій трапиться, якщо Ви налаштуєте блокування не на п'ять хвилин, а на більш тривалий час. У цьому випадку після зупинки процесу ці записи будуть заблоковані. Ну тобто Вам вже не можна буде просто так зупиняти процес, що може дуже негативно позначитися на Production платформі. Ця проблема вирішується вкрай легко: для правильної розподіленої роботи Вам слід самостійно написати процедури роботи з базою (тобто, реалізувати всі процедури для паралельної і розподіленої роботи, зробити свою реалізацію WorkflowPersistenceService ). Тут є, до речі, одна особливість: Вам не обов'язково працювати з MS Sql базою даних, можете поекспериментувати з іншими способами. На ділі, завдання вирішується за допомогою простої файлової кулі, працює швидко і правильно, однак це не модно.
 
 
Успішна робота під навантаженням
Насправді, її немає. Звичайно, Microsoft стверджує, що все стало прекрасно , але вони забули про один маленький графік: залежність кількості Activity в пам'яті від загального часу роботи (а раніше воно було таким ). На ділі воно не змінилося:
 
 image
 
Це квадратичний графік. Тут важливі не абсолютні значення часу, а залежність: наскільки довго у Вас буде все працювати, якщо складність бізнес-процесу зростатиме. Більш того, на ділі саме така залежність часу Execute від загальної кількості Activity в пам'яті, і не важливо — один це робочий процес або декілька. Наприклад, якщо у Вас 10 паралельних робочих процесів, то на обробку кожної маленької Activity буде витрачатися більше ресурсів, ніж якби був один робочий процес. Або інакше: 10 паралельних завдань обробляються довше, ніж 10 послідовних завдань. Причому, з нелінійної залежністю.
У попередній частині я написав, як працює Persistence Service: він забирає все з бази. На ділі такий фокус з 5000 паралельних складних робочих процесів згубний для системи: вона починає працювати з украй низькою швидкістю: 1-10 Activity на хвилину (!). І це за умови, що процесор буде завантажений майже на 100%. Проблема ясна, але як її вирішувати? Рішення: зробити свій обробник Activity, перевикористати Activity, Зробити емуляцію Ваших робочих процесів. За фактом Вам доведеться швиденько реалізувати базовий компонент Workflow, який займається стартом і зупинкою Activity. Це потрібно, щоб по-перше не допускати велику кількість запущених Activity на робочий процес (бо все гальмує), а по-друге щоб прискорити час сериализации / десеріалізациі (пошвидше виганяти зайвих з пам'яті) . Microsoft Workflow ніколи не видаляє відпрацьовану Activity. Вам же доведеться все реалізувати так, щоб завершення Activity не перебували в пам'яті.
 
 
Резюме
Я постарався описати частину проблем, які Вас чекають при роботі з Microsoft Workflow. На ділі тут є велика кількість нюансів, але вони більш-менш можна вирішити, і я впевнений, що Ви впораєтеся. За фактом, якщо у Вас на роботі постане завдання зробити свій настроюється бізнес процес, то краще все-таки почніть використовувати Microsoft Workflow. Для прототипу зійде. Більш того, при слабкій навантаженні вся ця система може працювати. Основні підстави відомі — вони вищі, вони цілком розв'язувані. До того ж, набагато краще працювати з системою, від якої відомо, що очікувати, ніж з тією, про яку є тільки маркетингова інформація. Ну а якщо навантаження почне рости, Ви зможете модуль за модулем перенести на свою ефективну реалізацію.
    
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.