Дневник на Dev: Възходът и падението на рояка зомбита

Повечето традиционни приложения за лични съобщения имат централизиран сървър, който ви позволява да съхраняват всички изпратени съобщения без гаранция за поверителността и без лимит от време.

Но за цялото удобство, което предлагат централизираните сървъри, винаги има шанс този, който ге управлява, в крайна сметка да ви прецака. Просто да се надяваме, че операторът няма да прослушва вашите съобщения, да споделя вашите разговори или да изтече вашата информация чрез обикновена, честна грешка.

Именно тези недостатъци ни тласнаха да използваме децентрализираната мрежа на Session. Но без централен сървър, който лесно да съхранява и препредава съобщения между потребителите, ние жертваме известно удобство.

И така, как да доставяме вашите съобщения без централен сървър?

Session използва неща, наречени рояци. Рояците са групи от 5-7 сервизни възли (управлявани от независими оператори от целия свят), които са „свързани“ помежду си. Когато създадете Session акаунт, вашият клиент ще бъде назначен на рояк. По този начин, ако сте офлайн, когато някой ви изпрати съобщение, той може да се съхранява във вашия рояк, докато не дойдете онлайн, за да го изтеглите.

Като цяло няма да сте в същия рой като човека, с когото се опитвате да се свържете, така че вашият клиент трябва да разберете в кой рояк е вашият контакт, преди да можете да им изпратите съобщение. След това копие от вашето съобщение се изпраща до три различни сервизни възли в рояка на вашия контакт – това дава някаква допълнителна застраховка,, че вашето съобщение ще бъде съхранено и доставено успешно.

Очевидно е критично, че съобщенията имат гарантирана доставка. Ако един рой борави с 90 процента от всички съобщения, ще изпаднем в сериозни проблеми с производителността. Но…. Session е свързана с поверителността – ние не знаем нищо за вашите не относно навиците на потребителите за техните съобщения, така че как можем да гарантираме, че съобщенията се разпределят равномерно в мрежата?

Трябваше на разработчиците протокол, който да може да доставя съобщения в мрежата на Session.

Мисията: Да се създаде начин за детерминистично разпределение на съхранението на съобщения приблизително равномерно в мрежата на Service Node.

Екипът от разработчици знаеха, че трябва да бъде изчислено детерминирано – което означава, че всеки може да се присъедини към мрежата, да следва набор от правила и да стигне до същите заключения за всеки даден рой. Но трябваше да се тества и, че не лесно да се предвиди в кой рой ще се свърже Service Node, в противен случай злонамерен потребител може теоретично да овладее цял тест за съхранение на съобщения за рояк и измама (това са прости тестове, които обслужващите възли използват гарантирайки, че всички връстници в рояка си съхраняват правилно съобщенията).

Ако един недоброжелател може да овладее рояк, той ефективно ще избере дали съобщенията ви някога ще бъдат доставяни. Това не звучи много достоверно, нали?

Така че трябваше на екипът да разработи как да групира всички служебни възли в рояка по сравнително непредсказуем начин и след това да намерим начин за равномерно разпределение на потребителите в тези рояци. Засега ще се съсредоточим върху втората част на този проблем: как да се разпределят потребителите в рояци.

Решението е да се картографират идентификаторите на рояка и публичните ключове на потребителите в една и съща цифрова линия, след което да се присвоят потребителите на идентификаторите на роя, до които са най-близо до линията. Публичните ключове се генерират на случаен принцип за нови потребители, но как се създават нови идентификатори на рояка?

Представете си, че имаме разпределение на роя, което изглежда така. Забележка: рояк № 10 обръща около рояк № 0.

В тази ситуация, рояци #6 и #9 ще получат твърде много трафик – всички публични ключове, кратографирани от 2½ – 6½, ще бъдат в № 6, публични ключове от 8 – 2½ ще бъдат в # 9, и публичните ключове от 6½ -8 ще бъдат в №6.

Може да се създаде нов рояк, който да облекчи товара, но ако произволно генерираме идентификатори на роя, както правим за публични ключове, може да се окажем с нещо подобно:

Симулациите показват много по-здравословно разпределение на натоварването, когато използваме този метод за запълване на празнината, който винаги гарантира, че най-големият рояк никога няма да бъде повече от двойно по-голям от най-малкия.

Реализацията на тази печеливша стратегия , само за да открием … кодът от теста беше разбит. Не е било забелязано по време на теста, тъй като даваше грешки, по които бяха невидими. Когато се обработваха статистическите данни на тестовете, се оказва, че един от скриптовете излагаше предположение за повече от 20 възли принадлежащи на един рой – много тревожно! По проект на възлите трябва да има от 5 до 7 възли.

Екипът беше заблуден, че системата работи добре дотогава е не бяха обърнали внимание на съответните кодове от месеци – така че това невнимание създаваше много голямо объркване. Изведнъж обаче се появи сериозен проблем точно преди пускането.

Оказва се, че самият алгоритъм беше неправилен и той се състоеше от един ред код в реализацията, причинявайки всички проблеми.

За да разберем какво става, трябваше да видим някои исторически данни за размерите роя. За съжаление, тази информация не съществуваше: нямахме съответните дневници и blockchain съхранява само най-новото състояние на роя. За да получим необходимите дневници, ще трябва да преиграем цялата блокчейн за себе си – от самото начало.

Когато направихме това, нашата реконструирана история за възлагане на роя показва възли, които се присъединяват към патологични рояци, изглежда, от нищото. След като прегледа екипът няколко други дневници и установи, че бяха извадени от употреба възли.

Наскоро бяхме въвели изведената от експлоатация – един вид чистилище за възли, преди те да бъдат отменени. По този начин операторите имат малко време да закърпят нездравословните си възли, преди да се загубят завинаги. Изведените от експлоатация възли никога не се броят към размера на роя – в противен случай може да се окаже рояк с дефектни възли.

Ето проблема: изведените от експлоатация възли автоматично се връщат към първоначалния си рояк, ако се върнат онлайн – напълно заобикаляйки ограниченията на размера на рояка.

И така, възлите, които трябваше да бъдат изведени от експлоатация, не възстановяваха своите стойности на идентификатора на рояка. Това направи решението доста просто: трябваше да се нулира стойността на идентификатора на роя за възлите в момента, в който те бъдат изведени от експлоатация. Изпълнението на тази поправка изисква само добавяне на един ред код, но отне няколко дни разработчиците, за да го установят.

Само по себе си, извън габаритните рояци вероятно биха добавили някаква неефективност към мрежата, но имаше друг, по-коварен проблем.

По дизайн, ако размерът на роя стане опасно малък, мрежата може да преразпредели здравните възли на рояка – по същество премахвайки рояка. Какво би станало, ако един изведен от употреба възел се върне в рояк, който вече не съществува?

Разработчиците на Session решиха да го направят на зомби – рояк, върнат от ръба. Преди кръпката, мрежата ще позволи на рояк да работи дори яко има само един възел – твърде малък, за да може да се счита за надежден.

За всички главоболия на екипа по пътя, в крайна сметка единственото, което трябваше да се добави един ред код – за да коригираме дилемата на рояка на зомбитата – всичко да застане на мястото си.

Абонирайте се за нашия бюлетин

За да получавате най-новите корпоративни блокчейн новини.