Ми належним чином у черзі та серіалізації?


13

Ми обробляємо повідомлення через різні сервіси (одне повідомлення торкнеться, ймовірно, 9 служб, перш ніж це буде виконано, кожен виконує певну функцію, пов'язану з IO). На даний момент у нас є комбінація найгіршого випадку (серіалізація контракту даних XML) та найкращого випадку (MSMQ в пам'яті) для продуктивності.

Характер повідомлення означає, що наші серіалізовані дані закінчуються приблизно 12-15 кілобайт, і ми обробляємо близько 4 мільйонів повідомлень на тиждень. Постійні повідомлення в MSMQ були для нас занадто повільними, і в міру зростання даних ми відчуваємо тиск з боку файлів, що відображаються в пам'яті MSMQ. Сервер працює на 16 ГБ пам'яті та зростає, лише для черги. Продуктивність також погіршується, коли об'єм пам'яті великий, оскільки машина починає мінятися. Ми вже виконуємо поведінку MSMQ з самоочищенням.

Я відчуваю, що тут є частина, в якій ми робимо неправильно. Я намагався використовувати RavenDB для збереження повідомлень і просто встановлення черги на ідентифікатор, але продуктивність там була дуже повільною (в кращому випадку 1000 повідомлень в хвилину). Я не впевнений, чи це результат використання версії розробки чи чого іншого, але нам, безумовно, потрібна більша пропускна здатність [1]. Концепція дуже добре працювала в теорії, але ефективність не відповідала цьому завданню.

У шаблоні використання є одна служба, яка виконує функцію маршрутизатора, яка робить все зчитування. Інші служби додаватимуть інформацію, засновану на їх сторонній гачок, і повертаються назад до маршрутизатора. Більшість об’єктів торкаються 9-12 разів, хоча близько 10% змушені певний час обходитись цими, поки треті сторони не реагують належним чином. Зараз сервіси пояснюють це та мають відповідну поведінку сну, оскільки ми використовуємо поле пріоритету повідомлення з цієї причини.

Отже, моє запитання, що таке ідеальний стек для передачі повідомлень між дискретними, але локальними машинами в середовищі C # / Windows? Я б зазвичай починав із BinaryFormatter замість серіалізації XML, але це кроляча діра, якщо кращим способом є завантаження серіалізації в сховище документів. Отже, моє запитання.

[1]: Характер нашого бізнесу означає, що чим швидше ми обробляємо повідомлення, тим більше заробляємо грошей. Ми емпірично довели, що обробка повідомлення пізніше тижня означає, що ми рідше заробляємо ці гроші. Хоча продуктивність "1000 в хвилину" звучить досить швидко, нам дійсно потрібна ця кількість вгору на 10 к / хв. Тільки тому, що я даю номери в повідомленнях на тиждень, не означає, що ми маємо цілий тиждень для обробки цих повідомлень.

=============== редагувати:

Додаткова інформація

На основі коментарів я додам уточнення:

  • Я не впевнений, що серіалізація - це наше вузьке місце. Я орієнтував додаток, і хоча серіалізація відображається на графіку теплоти, вона відповідає лише за, можливо, 2,5-3% використання CPU служби.

  • Я здебільшого стурбований постійністю наших повідомлень та можливим неправомірним використанням MSMQ. Ми використовуємо не транзакційні, непостійні повідомлення, щоб ми могли продовжувати роботу в черзі, і мені дуже хотілося б мати принаймні стійкі повідомлення, щоб вони пережили перезавантаження.

  • Додавання більше оперативної пам’яті є мірою зупинки. Машина вже пішла від 4 ГБ -> 16 ГБ оперативної пам’яті, і все важче і складніше її зняти, щоб продовжувати додавати більше.

  • Через зоряну схему маршрутизації програми, половина часу, коли об’єкт вискакує, потім висувається в чергу, вона взагалі не змінюється. Це знову піддається (IMO), щоб зберігати його в якомусь сховищі ключа-значення в іншому місці та просто передавати ідентифікатори повідомлень.

  • Зоряний зразок маршрутизації є невід'ємною частиною програми та не змінюватиметься. Ми не можемо застосувати цецентику, тому що кожен твір по шляху працює асинхронно (в опитувальному порядку), і ми хочемо централізувати повторне поведінку в одному місці.

  • Логіка програми написана на C #, об'єкти - незмінні POCO, цільовим середовищем розгортання є Windows Server 2012, і нам дозволяється вставати додаткові машини, якщо певна частина програмного забезпечення підтримується лише в Linux.

  • Мої цілі - підтримувати поточну пропускну здатність, зменшуючи при цьому пам’ять пам’яті та збільшуючи відмовостійкість з мінімальними витратами капіталу.


Коментарі були очищені, оскільки відповідні пункти були включені до питання.
ChrisF

Було б доцільно вирішити найактуальнішу проблему, перш ніж турбуватися про заміну підсистем черги (хоча це, можливо, все ж варто зробити в кінцевому підсумку). Той факт, що пам'ять зростає з-під контролю, говорить про те, що десь все ще є витоки. Що (якщо є) було зроблено профілювання пам'яті?
Ден Ліонс

@DanLyons: єдине зростання пам’яті в MSMQ. Ніхто насправді не говорить про це, але, мабуть, це відбувається через непостійні повідомлення, які всі відображені в пам'яті. Оскільки ми серіалізуємо багато даних, вона зберігає значну кількість пам'яті. Пам'ять (зрештою) відновлюється під час споживання повідомлень та внутрішнього очищення MSMQ.
Брайан Боттчер

Відповіді:


1

Ось кілька орієнтирів черги, які можуть вас зацікавити. MSMQ повинен бути здатний обробляти 10K повідомлень в секунду. Це може бути проблема конфігурації чи, можливо, клієнти не відстають від читання черги? Також зауважте, наскільки надзвичайно швидкий ZeroMQ у цих орієнтирах (близько 100 К повідомлень в секунду), він не пропонує можливості збереження, але він повинен перейти до того місця, де ви хочете бути ефективними.


4

У нас була дещо схожа ситуація кілька років тому із системою повідомлень у черзі (аудіо відбитки пальців у нашому випадку). Ми сильно цінували стійкість зачеплених пакетів даних, але ми з'ясували, що зав'язати все на диск і споживати чергу з диска було дуже дорого.

Якщо ми перейшли на черги на основі пам'яті, продуктивність була винятковою, але у нас була основна проблема. Час від часу споживачі черг ставали недоступними протягом значної кількості часу (елементи споживача та виробника в нашому випадку підключені через WAN), тож черга виробника зростала б до точки, яка стала некерованою і як у вашому випадку, як тільки споживання пам’яті було дуже високим, надмірна обмотка пам’яті під час заміни привела систему до повного сканування.

Ми розробили чергу, яку ми охрестили VMQueue (для черги віртуальної пам’яті дуже погана назва в ретроспективі). Ідея цієї черги полягає в тому, що якщо споживчий процес працює на номінал, іншими словами, обробляється досить швидко, щоб можна було тримати кількість зачеплених елементів нижче певного рівня, то в основному він має однакову продуктивність пам'яті, на основі черги. Однак, коли споживач сповільнюється або стає недоступним, а черга виробника зростає до певного розміру, тоді черга почне автоматично підключати елементи до диска «з-за» (використовуючиBinaryFormatterсеріалізація до речі). Цей процес забезпечує повний контроль над використанням пам’яті, а процес підкачки швидкий або принаймні набагато швидший, ніж підміна віртуальної пам’яті, що відбувається під час завантаження великої пам’яті. Після того, як споживачеві вдасться злити чергу під поріг, він продовжує працювати як чиста черга на основі пам'яті

Якщо система вийде з ладу або перезавантажиться, то черга зможе відновити всі підкачані елементи, які були збережені на диску, вона втратить лише ті елементи, які ще зберігалися в пам'яті до аварії. Якщо ви можете дозволити собі втратити обмежену кількість пакетів під час збоїв або перезавантаження, ця черга може бути корисною.

Якщо ви зацікавлені, я можу поділитися VMQueueвихідним кодом класу, щоб ви могли пограти з ним. Черга приймає будь-який клас, позначений як Serializable. Після створення черги ви встановлюєте розмір сторінки в кількості елементів. Інтерфейс класу практично не відрізняється від стандартного класу черги. Однак код дуже старий, (.net 1.1), тому загального інтерфейсу на жаль не існує.

Я знаю, що перехід від перевіреної технології MSMQ - це величезна ціна, проте ця черга надійно працює майже 6 років і дозволила нам вижити та відновитися після сценаріїв, де машина виробника не працює в автономному режимі вже кілька тижнів! Будь ласка, повідомте мене, якщо ви зацікавлені. :)


1

Система HP ProLiant ML350G5 отримує 82 тисячі транзакцій в хвилину - тобто має понад 8 разів більше, ніж Ви згадали пропускну здатність «10 к / хв».

Продуктивність: 82,774 т / мин

Також, чесно кажучи, я б тільки що зайшов з 64 або навіть 128 ГБ оперативної пам’яті - оперативна пам’ять - це дешево. Greenspun вказує на різницю між "киньте оперативну пам’ять на неї" і "отримайте розумного хлопця з освітою MIT, щоб оптимізувати його", і оперативна пам'ять виграє.

Він опинився на машині SQL Server, забезпеченій 64 ГБ оперативної пам’яті та кількома фронтальними машинами, на яких розміщені сторінки ASP.NET ... Сайт, swaptree.com, обробляє поточне членство понад 400 000 користувачів (швидко зростає) без труднощів ...

Зауважте, що "машина вже зайняла 16 ГБ оперативної пам'яті" - це далеко не достатньо, в статті вказано сервер, який обробляв 400 Кб користувачів на 64 ГБ оперативної пам'яті.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.