Peer-to-peer
Содержание
Peer-to-peer
Peer-to-peer - это архитектура передачи данных, основанная на идее равноправия всех участников сети. В сети отсутствуют выделенные серверы. В отличие от традиционных сетей, каждый из участников является как клиентом, так и сервером. Основным преимуществом такой сети является практически полная независимость работоспособности сети от её размера. В то время, как построить и поддерживать сервер на сотни тысяч пользователей является непростой задачей, peer-to-peer сети отлично с этим справляются.
Идея peer-to-peer общения заключается в том, что каждый peer знает и поддерживает информацию о других участниках. Когда новый клиент подключается к сети, он может узнать у любого пира информацию о том, где и какие файлы сейчас доступны. Когда клиент начинает скачивает файл себе на компьютер, то скачанные части этот файла сразу становятся доступны для скачивания другим пользователям. Никто не даёт гарантию, что каждый сервер будет находиться длительное время в сети и давать скачивать информацию, напротив -- ситуация, когда сервер пропадает в процессе загрузки, является естественной. В данном случае будет найден новый сервер, который может продолжить передачу данных. Для поддержания списка активных peer-ов каждый сервер посылает другим серверам heartbeat. Heartbeat -- это сообщение, которое один сервер посылает другому, чтобы сказать ему, что он жив. Соответственно, если heartbeat долго не приходит, значит этот сервер нужно удалить из списка активных peer-ов. Постоянно обмениваться heartbeat-ом с большим количеством серверов трудоёмко. Поэтому у каждого сервера есть два параметра -- нижняя и верхняя граница на размер списка активных серверов. Когда это количество становится ниже нижней границы, запускается поиск новых участников. Сервер запрашивает у других серверов список активных peer-ов и добавляет некоторых из них в свой список, но при этом следит за тем, чтобы размер списка не превысил верхнюю границу.
Частично децентрализованные сети
В некоторых peer-to-peer сетях кроме равноправных node присутствуют сервера, которые выполняют административные функции, такие как поддержка базы онлайн пользователей. К частично децентрализованным сетям относятся например eDonkey, BitTorrent, Direct Connect, The Onion Router.
BitTorrent протокол
Протокол BitTorrent был разработан в 2001 году Коэном Брахмом, чтобы позволить набору узлов быстро и легко обеспечивать общий доступ к файлам.
Сам протокол состоит в следующем: есть небольшой торрент-файл, содержащий информацию о трекере, который следит за файлом, и список сегментов, из которых состоит файл: для сегмента хранится 160-битовый SHA-1 соответствующего сегмента файла (обычный размер сегмента -- 64-512 кб). Таким образом, скачав файл, можно посчитать от него хеши и проверить, все ли скачалось без ошибок. Кроме торрент-файла есть трекер: сервер, который следит за состоянием пиров -- узлов, имеющих отношение к раздаче. Пир, получив торрент-файл, подключается к трекеру и узнает список сидов -- пиров, у которых уже есть некоторые сегменты файла, готовые их отдать. Узнав адрес сида, у которого можно что-то скачать, клиент уже обращается напрямую к нему и скачивает у него файл. Таким образом, все данные идут напрямую от пира к пиру (peer-to-peer), а трекер участвует лишь в качестве координатора процесса.
Таким образом, протокол не является централизованным (нет никаких выделенных хранилищ с данными), но решает проблему "А где же мне найти, где бы скачать вот этот фрагмент файла".
Для того, чтобы не было проблем с поиском какой-то части файла, трекер сначала предлагает загружать сегменты, которые есть у наименьшего числа участников сети. Это позволяет избежать проблемы, характерной для последовательной загрузки файла, когда много участников скачали почти весь файл, а вот самого конца сейчас ни у кого нет.
Система работает хорошо, когда каждый ее участник скачал документ, а потом еще и остался на его раздаче, отдавая свой долг перед родиной. К сожалению, бывает так, что клиент скачал все, что ему нужно, и решил не оставаться на раздаче -- таких пиров называют личерами. Если в системе много личеров, то раздавать файлы некому, и скорость скачивания падает. Для решения этой проблемы трекер может применить систему поощрений: отдавать пиру очередной сегмент, лишь если его отношение "скачал/отдал" не меньше, чем какое-то конкретное число, мотивируя клиентов оставаться на раздаче, повышая свой рейтинг. К сожалению, это не всегда хорошо работает, так как бывают компьютеры, имеющие хорошую скорость скачивания и малую скорость отдачи. Таким клиентам сложно иметь хороший рейтинг, и они в итоге страдают от этой системы.
Слабым местом системы можно назвать систему трекеров: трекер должен быть всегда в сети, и быть готовым координировать большое количество пиров. Это, конечно, значительно более простая работа, чем явно пересылать каждому желающему целые файлы, но тоже достаточно ресурсоемкая. Несмотря на это, в мире сейчас немало больших торрент-трекеров, несмотря на борьбу с ними компаний, занимающихся защитой авторских прав. Торрент-трекеры действительно всегда были оплотом пиратского контента -- трекеру-то ничего не предъявишь, что он хранит нелицензионный и не предназначенный для распространения контент, а участникам сети особо ничего и не предъявишь (бывают прецеденты, но они достаточно редки).
Friend-to-Friend
Friend-to-Friend -- это разновидность peer-to-peer сетей, в которой пользователи обмениваются данными только с теми peer-ми, которым они доверяют. Для аутентификации используются цифровые подписи и пароли. В отличие от P2P пользователи не могут посмотреть список участников F2F сети, кроме своих друзей. Из достоинств таких сетей можно отметить, что F2F являются сильно более защищёнными от хакерских атак, а также в них сильно меньше личеров. Использование F2F-сетей позволяет избегать атак типа mitm (man in the middle), то есть пользователи могут без опасений обмениваться секретными данными (например, крипто-ключами) со своими друзьями.
DHT
Рассмотрим пример децентрализованной структурированной P2P сети.
Предположим, что мы пытаемся поддерживать какую-то DHT: Distributed Hash Table, и хотим, чтобы система была децентрализованная. Скажем, что ключами нашей хеш-таблицы будут, например, 160-битные числа (какой-то хеш объекта). Назначим каждому узлу 160-битное число (например, случайно), и каждый узел будет отвечать за объекты, для ключей которых число в этой вершине ближайшее среди всех чисел вершин.
Для инициализации можно считать, что у нас достаточно мало узлов в сети, каждый узнает ключи других узлов, и инициализирует свою часть хеш-таблицы.
Предположим, что клиент подключился к одному из узлов сети, и хочет найти сервер, отвечающий за какой-то ключ k. Простой способ -- заставим каждый узел хранить следующий и предыдущий (по ассоциированному ключу) узлы, и тогда, если ключ находится не в зоне нашей ответственности, можно спокойно передать запрос следующей вершине. Если какой-то узел хочет выйти из сети, он говорит своим соседям, что больше работать не будет, и передает им свои части таблицы. Подключение новых узлов работает аналогично.
К сожалению, это работает медленно: пробегать для каждого запроса в среднем половину серверов -- не лучшая идея. Вместо этого можно хранить что-то вроде двоичных подъемов: не только ссылку на следующий сервер, но и ссылку на сервера, отвечающие за ключ (k+2^0)%2^160, (k+2^1)%2^160), etc. Таким образом, мы сможем дойти до нужного сервера всего за логарифм операций.
Для увеличения надежности можно хранить ссылку не только на предыдущую/следующую вершины, но на несколько (3-5) ближайших. Это нужно для того, чтобы при внезапном отключении узла, который не успел договориться с соседями, не прерывать связность сети. Кроме того, нужно периодически отсылать сообщения серверам, на которые у нас ведут быстрые ссылки: при добавлении вершины честно пересчитать все переходы на 2^n во всех узлах сети не представляется возможным, а вот отдать эту задачу самим узлам, чтобы они периодически проверяли корректность своих данных -- нормальная идея.
Таким образом, мы рассмотрели пример децентрализованной структурированной P2P сети.
Bitcoin
Ещё одним из примеров использования peer-to-peer соединения является криптовалюта bitcoin. Bitcoin -- это децентрализованная цифровая валюта работающая только в сети интернет. Эмиссия валюты происходит по всему миру посредством поиска решения трудновычислимых математических задач. Все транзакции происходят непосредственно между участниками без использования посредников. Программы, которые работают с bitcoin-ми поддерживают между собой peer-to-peer соединение после того как формируется новый блок транзакций он рассылается broadcast другим участникам сети, которые свою очередь делятся этой информацией с другими серверами. Стоит отметить, что bitcoin устроен так, что новые блоки транзакций появляются относительно редко -- примерно раз в 10 минут. Поэтому это не приводит к сильной загрузке сети.