Несколько лет назад в мире начался настоящим бум Децентрализованных, P2P решений. Возможно, катализатором этого процесса стали Крипто-валюты (blockchain, bitcoin). Возможно — желание людей получить воистину приватный интернет без слежки и всего остального. Как бы там не было, теперь не возможно делать вид, что P2P-технологии нам не нужны. Это наше будущее.
Честно говоря, ещё совсем недавно я был крайне далёк от P2P-технологий (да и щас я, на самом деле, не особо продвинулся). Поэтому в один момент времени захотелось понять, что это за технологии (протоколы, а также их реализации), и как это всё примерно работает.
Для изучения Децентрализованных решений, было решено взять простую задачку — файлообменник (File sharing). В конечном итоге, хотелось получить программу, которая позволяла бы двум произвольным пользователям обменяться некоторыми файлами. Гланвое требование — serverless (не, не так, как в Амазоне, а так, чтобы не было центрального звена, которое бы потребовалось для выполнения обмена). В общем, что-то типа BitTorrent.
В ходе работы над данным продуктом, я узнал несколько вещей, которыми хотелось бы поделиться.
В первую очередь, нужно отменить две проблемы, которые, по момему мнению, являются главными в P2P-мире. Речь идёт о NAT (Network address translation), а также о необходимости использования Консенсусов для сходимости системы. Про NAT я поговорю далее, а про алгоритмы консенсусов уже написано довольно много всего, можно почитать например это — https://habr.com/company/bitfury/blog/327468/, https://en.wikipedia.org/wiki/Paxos_(computer_science) и https://en.wikipedia.org/wiki/Raft_(computer_science). Важно! Алгоритмы Paxos и Raft используютс в классических распределенных системах (например, в NoSQL-решениях).
Про NAT… Это жопа, честно. Если мы разрабатываем классические приложения, они запускаются в известной нам среде. Это сервера с белыми IP-адресами (чаще всего, даже IPv4). В случае, когда наша программа работает на клиентской стороне, у нас вообще нет никаких гарантий. Всё, что мы знаем — это наличие возможности сделать исходящий сетевой запрос. У клиента может быть один NAT. А ещё бывает несколько слоёв NAT — когда вам продаёт интернет мелкий провайдер, который является простым посредником некоторого большого провайдера, и этот мелкий провайдер сам находится за NAT. Несколько NAT наиболее часто встречаются на мобильных телефонов (а это грустно, ведь P2P и IOT (Internet of things) стоят бок о бок друг с другом).
Сущесвтует несколько концепций, как обойти NAT — NAT traversal. В общем-то, я бы выделил из всего этого следующее:
«Как-то мутно всё это дело звучит. Я просто хотел написать P2P-программу на своём любимом JavaScript, а не спеки читать.» — мысли большинства из нас. Увы, Децентрализованная разработка — это сложно. Тут надо понимать, и как сеть работает, и какие вообще клиенты бывают. Однако не стоит расстраиваться. Есть вполне себе высокоуровневые решения, скрывающие от нас всю боль децентарализованной разработки.
В первую очередь, нужно вспомнить об WebRTC — https://www.html5rocks.com/en/tutorials/webrtc/infrastructure/. Изначально WebRTC создавался, как решение для браузерного мультимедия — телефонных разговоров, видео чатов и всего такого. Однако позже WebRTC стали просто использовать для реализации P2P-программ. Это связано с тем, что WebRTC — это реализация ICE (о котором шла речь выше). То есть, тут есть всё, что вам уже знакомо — TURN и STUN сервера, а также UDP hole punching. Важно, что в WebRTC есть нативное API для P2P-коммуникации — установления соединения, а также передачи данных — RTCDataChannel.
Что делать, если хочется WebRTC, а вам приходится писать не на богоподобном JavaScript, а на языке врагов — Go, C++, Java, или Rust. Ну, варианта два. Либо реализовать WebRTC самому, либо взять готовую реализацию. Например, для Golang — https://github.com/pions/webrtc.
Кстат, вот программа для обмена файлов на WebRTC — https://www.sharedrop.io/.
Возможно, вам не понравится WebRTC из-за большого фокуса на мультимедия. В этом случае, можно взять одну из готовых Relay-реализаций. Есть множество P2P-проектов, цель которых — сделать свободный интернет без централизации. Таких решений много, есть уже и весьма стабильные реализации.
Я могу рекомендовать посмотреть на https://github.com/syncthing/syncthing — проект, который строит Бизнесово систему для синхронизации файлов на всех ваших компьютерах. Это что-то типа Resilio Sync и BitTorrent.
Однако у Syncthing есть и идеологическая цель — свободность интернета. Поэтому эти ребята кроме реализации программы для обмена файлами, попутно сделали набор протоколов, каждый из которых помогает организовать P2P-систему.
Как работает Syncthing? Система состоит из серверов нескольких типов. Во-первых, это Discovery Server-а. Они нужны, для того чтобы клиенты могли регистрироваться в системе, и видеть друг друга на сетевом уровне. Во-вторых, это Relay-сервера (хнык-хнык).
Relay-сервера — централизованная часть системы — нужны, как fallback — когда не удаётся установить P2P-соединение, трафик начинает идти через эти ноды. Relay-нодой тут может быть любой человек — достаточно поднять на своей машине этот сервис (трафик шифруется, так что это не так страшно, но, факт наличия обмена между нодами не скрывается).
В заключение, ещё раз хочется отметить важность темы Децентрализованных вычислений и P2P. Даже, если забыть про приватность. Компаниям крайне дорого проводить вычисления на своём железе, а также гонять трафик через себя. Поэтому, если в будущем появится способ реализовать всё это дело на клиентской стороне, то, думаю, многие фирмы выбирут это. Будем верить, что в скором времени реализация P2P-програм будет такой же простой, как сейчас просто рализовать централизованную программу.
Категории: Программирование