Ми обробляємо повідомлення через різні сервіси (одне повідомлення торкнеться, ймовірно, 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.
Мої цілі - підтримувати поточну пропускну здатність, зменшуючи при цьому пам’ять пам’яті та збільшуючи відмовостійкість з мінімальними витратами капіталу.