Скільки TPS у вашому блокчейні?

Улюбленим питанням про будь-яку розподілену систему від нетехнічного фахівця є “Скільки tps у вашому блокчейні?”. Однак, назване у відповідь число зазвичай має мало спільного з тим, що хотів би почути запитувач. Насправді, він хотів запитати "чи підійде ваш блокчейн під мої бізнес вимоги", і ці вимоги - це не одне число, а безліч умов - тут і стійкість до відмов мережі, і вимоги до фінальності, розміри, характер транзакцій і безліч інших параметрів. Отже, відповідь на запитання “скільки tps” навряд чи буде простою, і майже ніколи не буде повною. Розподілена система з десятками і сотнями вузлів, що виконують досить складні обчислення, може перебувати у величезній кількості різних станів, пов'язаних зі станом мережі, вмістом блокчейна, технічними збоями, економічними проблемами, атаками на мережу та безліччю інших причин. Етапи, на яких можливі проблеми з продуктивністю, відрізняються від традиційних сервісів, а сервер блокчейн-мережі — це мережевий сервіс, що поєднує в собі функціонал бази даних, web-сервера і torrent-клієнта, що робить його вкрай складним у плані профілю навантаження на всі підсистеми. : процесор, пам'ять, мережа, storage

Так вийшло, що децентралізовані мережі та блокчейни є досить специфічним та незвичним софтом для розробників централізованого ПЗ. Тому я хотів би висвітлити важливі аспекти продуктивності та стійкості децентралізованих мереж, підходи до їх вимірювання та знаходження bottlenecks. Ми розглянемо різні проблеми продуктивності, що обмежують швидкість надання сервісу користувачам блокчейнів та відзначимо особливості, характерні для цього виду софту.

Етапи запиту сервісу клієнтом блокчейна

Для того, щоб чесно говорити про якість будь-якого більш-менш складного сервісу, потрібно врахувати не лише середні значення, а й максимальні/мінімальні медіани, персентилі. Теоретично, можна говорити про 1000 tps в якомусь блокчейні, але якщо 900 транзакцій виконалися з величезною швидкістю, а 100 - "зависли" на кілька секунд, то середній час, зібраний по всіх транзакціях - це не зовсім чесна метрика для клієнта, який за кілька секунд не зміг завершити угоду. Тимчасові «ями», викликані пропущеними раундами консенсусу або поділом мережі, можуть сильно зіпсувати сервіс, який на тестових стендах показував чудову продуктивність.

Щоб ідентифікувати такі bottleneck і необхідно добре розуміти етапи, на яких реальний блокчейн може відчувати труднощі при обслуговуванні користувачів. Давайте опишемо цикл доставки та процесингу транзакції, а також отримання нового стану блокчейну, з якого клієнт може переконатися, що його транзакція була оброблена та врахована.

  1. транзакція формується на клієнті
  2. транзакція підписується на клієнта
  3. клієнт вибирає одну з нід і відправляє до неї свою транзакцію
  4. клієнт підписується на оновлення state database ноди, очікуючи появи результатів виконання своєї транзакції
  5. нода поширює транзакцію через p2p мережі
  6. кілька або один BP (block producer) процесують накопичені транзакції, оновлюючи state database
  7. BP формує новий блок, обробивши необхідну кількість транзакцій
  8. BP розповсюджує новий блок по p2p мережі
  9. новий блок доставляється до ноди, до якої звертається клієнт
  10. нода оновлює state database
  11. нода бачить оновлення, що стосується клієнта, і надсилає йому повідомлення про транзакцію

Тепер давайте детальніше розберемо ці етапи та опишемо потенційні проблеми з продуктивністю на кожному етапі. На відміну від централізованих систем ми також розглянемо виконання коду на клієнтах мережі. Досить часто при вимірі tps час процесингу транзакцій збирають із нід, а не з клієнта – це не зовсім чесно. Клієнту начхати, наскільки швидко нода запроцесувала його транзакцію, найважливіше для нього — момент, коли достовірна інформація про цю транзакцію, включену до блокчейну, стане доступною йому. Саме ця метрика і є, по суті, часом виконання транзакції. Це означає, що різні клієнти, навіть відправляючи ту саму транзакцію, можуть отримати зовсім різні часи, які залежать від каналу, завантаженості та близькості ноди, тощо. Так що необхідно вимірювати цей час на клієнтах, оскільки саме цей параметр потрібно оптимізувати.

Підготовка транзакції на стороні клієнта

Почнемо з перших двох пунктів: транзакція формується та підписується клієнтом. Як не дивно, це теж може бути bottleneck-ом продуктивності блокчейну з погляду клієнта. Це незвично для централізованих сервісів, які всі обчислення та операції з даними забирають собі, а клієнт просто готує короткий запит, здатний запросити великий обсяг даних чи обчислень, отримуючи готовий результат. У блокчейнах клієнтський код стає дедалі більш потужним, а блокчейн ядро ​​— дедалі більше легковажним, а потужні обчислювальні завдання прийнято віддавати клієнтському софту. У блокчейнах існують клієнти, які можуть готувати одну транзакцію досить довго (я говорю про різні merkle proof-и, succinct proof-и, threshold підписи та інші складні операції на стороні клієнта). Хорошим прикладом легкої on-chain верифікації та важкої підготовки тренакции на клієнті є доказ приналежності списку на основі Merkle-tree, ось стаття.

Також не варто забувати, що клієнтський код не просто надсилає транзакції в блокчейн, а спочатку запитує стан блокчейну — а ця діяльність може впливати на завантаженість мережі та блокчейн нод. Так що, проводячи вимірювання, розумним буде емулювати якомога повніше поведінка клієнтського коду. Навіть якщо у вашому блокчейні звичайні легкі клієнти, які ставлять звичайний цифровий підпис на найпростішу транзакцію з перекладу якого-небудь asset-а, з кожним роком масивних обчислень на клієнті все одно стає більше, криптоалгоритми міцнішають, і ця частина процесингу може перетворитися на вагу майбутньому. Тому будьте обережні, і не пропустіть ситуацію, коли в транзакції, що триває 3.5s, 2.5s йде на підготовку та підписання транзакції, і 1.0s-на відправку до мережі та очікування відповіді. Для оцінки ризиків появи цього bottleneck потрібно збирати метрики з клієнтських машин, а не лише з блокчейн-нод.

Відправлення транзакції та моніторинг її статусу

Наступним етапом є відправка транзакції у вибрану блокчейн-ноду та отримання статусу прийняття її в пул транзакцій. Цей етап схожий на звичайне звернення до бази даних, але повинна записати транзакцію в пул і почати поширювати інформацію про неї через мережу p2p. Підхід до оцінки продуктивності тут нагадує оцінку роботи традиційних мікросервісів Web API, причому самі транзакції в блокчейнах можуть оновлюватися, активно змінювати статус. Взагалі оновлення інформації про транзакцію в деяких блокчейнах може відбутися кілька разів, наприклад при перемиканнях між форками ланцюжка або коли BP повідомляють про намір включити транзакцію в блок. Обмеження обсяг цього пулу і кількість транзакцій у ньому можуть впливати на продуктивність блокчейна. Якщо пул транзакцій забитий до максимально можливого розміру, або не міститься в оперативній пам'яті, продуктивність мережі може різко впасти. Блокчейни не мають централізованих засобів захисту від потоку сміттєвих повідомлень, і якщо блокчейн підтримує транзакції великого обсягу і низькі комісії, це може призвести до переповнення пулу транзакцій — це ще один потенційний bottleneck продуктивності.

У блокчейнах, клієнт оправляє транзакцію в будь-яку ноду блокчейна, що йому сподобалася, хеш транзакції зазвичай відомий клієнту ще до відправки, так що все що йому потрібно - домогтися з'єднання і після передачі чекати коли блокчейн змінить свій стан, включивши його транзакцію. Зауважимо, що вимірюючи «tps» можна отримати різні результати для різних способів підключення до ноди блокчейна. Це може бути звичайний HTTP RPC або WebSocket, що дозволяє реалізувати патерн subscribe. У другому випадку клієнт отримає повідомлення раніше, а нода витратить менше ресурсів (переважно пам'яті та трафіку) на відповіді про стан транзакції. Так що при вимірі "tps" необхідно враховувати спосіб підключення клієнтів до нод. Тому, для оцінки ризиків появи цього bottleneck-а, benchmark блокчейна повинен вміти емулювати клієнтів і з WebSocket і з HTTP RPC запитами, у частках, що відповідають реальним мережам, а також змінювати характер транзакцій та їх розмір.

Для оцінки ризиків появи цього bottleneck потрібно також збирати метрики з клієнтських машин, а не тільки блокчейн-нод.

Передача транзакцій та блоків по p2p мережі

У блокчейнах передачі між учасниками транзакцій і блоків використовується peer-to-peer (p2p) networking. Транзакції поширюються по мережі, починаючи з однієї з нід, поки не досягають peer-ів-block producer-ів, які упаковують транзакції в блоки і за допомогою того ж p2p поширюють нові блоки по всіх нодах мережі. Основа більшості сучасних p2p мереж – різні модифікації протоколу Kademlia. Ось хороший короткий огляд цього протоколу, а ось стаття з різними вимірами в мережі BitTorrent, за якою можна зрозуміти, що цей вид мереж складніший, і менш передбачуваний, ніж жорстко налаштована мережа централізованого сервісу. Також, ось стаття про вимір різних цікавих метрик для нод Ethereum.

Якщо коротенько, кожен peer у таких мережах підтримує свій власний динамічний список інших peer-ів, у яких запитує блоки інформації, що адресуються за вмістом. При отриманні запиту peer або віддає потрібну інформацію, або передає запит наступному псевдовипадковому peer зі списку, а отримавши відповідь, передає його запитувачу і на деякий час кешує його, віддаючи цей блок інформації раніше наступного разу. Таким чином популярна інформація виявляється у великій кількості кешів у великої кількості peer-ів, а непопулярна поступово витісняється. Peer-и ведуть облік хто кому скільки передав інформації, і мережа намагається стимулювати активних роздаючих, підвищуючи їхній рейтинг і забезпечуючи їм більш високий рівень сервісу, автоматично витісняючи неактивних учасників зі списків peer-ів.

Отже, транзакцію тепер треба поширити мережею, щоб її побачили block-producer-и і включили в блок. Нода активно «роздає» нову транзакцію всім охочим і слухає мережу, очікуючи блок, в індексі якого з'явиться потрібна транзакція, щоб повідомити клієнта, що очікує. Час, поки мережа перекидає одна одній інформацію про нові транзакції та блоки в p2p мережах залежить від дуже великої кількості факторів: кількості чесних, що працюють поруч (з мережевого погляду) нід, «прогрітості» кешів цих нід, розміру блоків, транзакцій, характеру змін , географії мережі, числа нід та ще безлічі факторів. Комплексні виміри метрик швидкодії в таких мережах - складна справа, необхідно одночасно оцінювати час обробки запитів і на клієнтах, і на peer-ах (блокчейн нодах). Проблеми в якомусь з p2p механізмів, неправильне витіснення та кешування даних, неефективне управління списками активних peer-ів, і безліч інших факторів можуть стати причиною затримок, що впливають на ефективність всієї мережі в цілому, і цей bottleneck — найскладніший для аналізу, тестування та інтерпретація результатів.

Процесинг ланцюжка блоків та оновлення state database

Найважливішою частиною роботи блокчейна є алгоритм консенсусу, його застосування до нових, отриманих із мережі блоків та процесинг транзакцій із записом результатів у state database. Додавання нового блоку в ланцюжок і наступний вибір основного ланцюжка повинен працювати максимально швидко. Однак, у реальному житті «повинен» не означає «працює», і можна, наприклад, уявити собі ситуацію, коли два довгі конкуруючі ланцюжки постійно перемикаються між собою, змінюючи метадані тисяч транзакцій у пулі на кожному перемиканні, і виробляючи постійні відкати стану state database. Цей етап, у плані визначення bottleneck простіше, ніж мережевий p2p шар, т.к. виконання транзакцій та алгоритм консенсусу суворо детерміновані, і виміряти щось тут простіше.
Головне – не сплутати випадкову деградацію продуктивності цього етапу з проблемами мережі – ноди повільніше віддають блоки та інформацію про основний ланцюжок і для зовнішнього клієнта це може виглядати як повільна мережа, хоча проблема криється зовсім в іншому місці.

Для оптимізації продуктивності на цьому етапі корисно збирати та моніторити метрики з самих нод, і включати в них ті, що стосуються оновлення state-database: кількість блоків, що обробляються на ноді, їх розмір, кількість транзакцій, кількість перемикань між форками ланцюжків, кількість невалідних блоків , час роботи віртуальної машини, час фіксації даних тощо. Це дозволить не сплутати мережеві проблеми з помилками в алгоритмах процесингу ланцюжків.

Віртуальна машина, що процесує транзакції, може бути корисним джерелом інформації, здатної оптимізувати роботу блокчейна. Кількість алокацій пам'яті, кількість read/write інструкцій, та інші метрики, що стосуються ефективності виконання коду контрактів можуть дати багато корисної інформації розробникам. У той же час, смарт-контракти - це програми, а значить теоретично вони можуть споживати будь-які з ресурсів: cpu/memory/network/storage, так що процесинг транзакцій - досить невизначений етап, який також сильно змінюється при переході між версіями і при зміну коду контрактів. Тому метрики, що стосуються процесингу транзакцій, також потрібні для ефективної оптимізації продуктивності блокчейну.

Отримання клієнтом повідомлення про включення транзакції до блокчейну

Це завершальний етап отримання сервісу клієнтом блокчейну, в порівнянні з іншими етапами тут немає великих накладних витрат, але все одно варто враховувати можливість отримання клієнтом об'ємної відповіді від ноди (наприклад, смарт-контракт, що віддає масив даних). У будь-якому випадку, саме цей момент є найважливішим для того, хто поставив питання «а скільки tps у вашому блокчейні?», т.к. у цей час і фіксується час отримання сервісу.

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

Висновок

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

  1. криптографічні перетворення, побудова доказів
  2. peer-to-peer networking, реплікація транзакцій та блоків
  3. процесинг транзакцій, виконання смарт-контрактів
  4. застосування змін у блокчейні до state database, оновлення даних про транзакції та блоки
  5. read-only запити до state database, API блокчейн ноди, subscription сервіси

Взагалі технічні вимоги до нодів сучасних блокчейнів вкрай серйозні - це швидкі CPU для криптографії, великий обсяг оперативної пам'яті для того, щоб зберігати і швидко звертатися до state database, взаємодія, що використовує велику кількість одночасно відкритих з'єднань, об'ємний storage. Такі високі вимоги та різноманітність різних типів операцій неминуче призводять до того, що ресурсів у нід може бракувати, і тоді будь-який з розглянутих вище етапів може стати черговим bottleneck-ом для загальної продуктивності мережі.

Розробляючи та оцінюючи продуктивність блокчейнів, вам доведеться враховувати всі ці моменти. Для цього потрібно збирати та аналізувати метрики одночасно з клієнтів та нод мережі, шукати кореляції між ними, оцінювати час надання сервісу клієнтам, враховувати всі основні ресурси: cpu/memory/network/storage, розуміти як вони використовуються та впливають один на одного. Все це робить порівняння швидкостей різних блокчейнів у вигляді «скільки TPS» вкрай невдячним заняттям, оскільки існує безліч різних конфігурацій та станів. У великих централізованих системах, кластерах із сотень серверів, ці проблеми також складні і також вимагають збирання великої кількості різних метрик, але в блокчейнах, через p2p мереж, віртуальних машин, процесових контракти, внутрішньої економіки, число ступенів свободи набагато більше, що робить тест навіть на кількох серверах непоказовим і таким, що показує лише вкрай приблизні значення, майже не мають зв'язку з реальністю.

Тому, при розробці в ядрі блокчейну, для оцінки продуктивності та відповіді на питання «чи покращилося порівняно з минулим разом» ми використовуємо досить складний софт, що оркеструє запуск блокчейну з десятками вузлів та автоматичним запуском бенчмарку та збором метрик, без цієї інформації вкрай складно налагоджувати протоколи, які працюють із безліччю учасників.

Отже, отримавши питання «скільки TPS у вашому блокчейні?», запропонуйте співрозмовнику чаю і уточніть, чи готовий він ознайомитися з десятком графіків, а також вислухати всі три короби проблем продуктивності блокчейнів і вашими пропозиціями щодо їх вирішення.

Джерело: habr.com

Додати коментар або відгук