Русский
Русский
English
Статистика
Реклама

Перевод Азбука libp2p от Textile, часть 2

Переводстатьиначального уровня в блоге проектаTextileот 12 декабря 2019 г.

Впредыдущей статьемы начали с вопроса: Как подойти к своему первому p2p-приложению? После недолгих размышлений мы быстро пришли к выводу, что решениене полагаться на централизованный сервери сосредоточиться на том, чтобы сделать приложение дляравноправных узлов, сопряжено с множеством дополнительных сложностей. Две основные группы проблем - этосостояние приложенияиинфраструктурное разнообразие протоколов. К счастью, мы обнаружили, что нам не нужно изобретать велосипед, заново решая груду инфраструктурных задач - вместо того мы можем использовать великолепный сетевой p2p-стек: библиотеку libp2p.

В сегодняшнем посте мы пойдем немного дальше и представим игрушечное приложение, чтобы почувствовать, как на самом деле можно что-то разрабатывать с помощью libp2p, и, надеюсь, мотивировать вас создать собственное p2p-приложение. Серьезно, вы удивитесь, насколько это просто!

Приложение

Сразу оговоримся, наша программа нынче будет написана на языкеGo, с использованием библиотекиgo-libp2p. Если вы ещё не знакомы с этим языком, настоятельно рекомендуем ознакомиться. Он действительно хорош для приложений, имеющих дело с параллелизмом и сетевыми взаимодействиями (такими, как например, обработка множества p2p-соединений). Большинство библиотек IPFS/libp2p имеют свои базовые реализации, написанные на Go. Прекрасным введением в Go являетсятур на golang.org.

Итак, наша программка будет простым приложением для пинг-понга с некоторыми добавочными настройками, чтобы сделать её более интересной, в отличие от обычных безыскусных примеров. Вот некоторые особенности нашего приложения (не волнуйтесь, мы расскажем подробней об этих пунктах позже):

  • По умолчанию приложение цепляется к свободному TCP-порту.

  • Если указан флаг quic, оно также подключится к прослушиваемому порту QUIC, который станет предпочтительным адресом узла для игры в пинг-понг.

  • Узел будет использовать службу mDNS для обнаружения новых узлов в локальной сети.

  • На каждом вновь обнаруженном узле (скажем, узле A) наше приложение будет запускать собственный протокол sayMyAddr (мы его реализуем), который будет узнавать для нас предпочтительный адрес для игры в пинг-понг этого узла.

  • Мы подключаемся к узлу А, используя предпочитаемый им адрес - и запускаем танец Пинг-Понг. Другими словами, мы запустим ещё один наш самопальный протокол, посредством которого отправим сообщение Ping, а узел A ответит нам сообщением Pong. Круть!

Даже для такой простой системы (если мы хотим сделать p2p-приложение) потребуется принять ряд отдельных решений. Для начала, надо будет ответить на следующие вопросы:

  • Какой транспортный протокол (TCP, QUIC и т.п.) использовать?

  • Какой механизм обнаружения других узлов в сети (например, mDNS) применить - то есть, как мы узнаем о других узлах, использующих наше приложение?

  • Как наши собственные протоколы (Streams) будут работать? - то есть, как мы будем поддерживать двунаправленную связь с другими узлами?

Решения этих вопросов независимы друг от друга, и, к счастью, модульность libp2p прямо-такизаставляетнас избегать их объединения. Что ж, плюс один за хороший дизайн библиотеки!

Ныряем в код!

Рекомендуем вам сразу же начать играться с кодом приложения. Он содержит массу комментариев, чтобы помочь читателю впутешествии понимания!Кроме того, здесь мы набросаем общий обзор, который может стать хорошей преамбулой для подробного прочтения кода. Не стесняйтесь клонировать репо себе на компьютер, дабы и вы могли запачкать руки:

КОД:ВДЕЛИТЬ ВСЁ

git clone git@github.com:textileio/go-libp2p-primer-article.gitcd go-libp2p-primer-articlecode . // Нам нравится VSCode, ну а вы - сами с усами ;)

Далее: начнём сmain.go, где вы можете лицезреть, как создаётся и запускается хост libp2p. Дополнительно здесь мы указываем, какие сетевые транспортные протоколы будет поддерживать наш хост. Заметьте, что если для флага -quic установлено значение true, мы добавляем новую привязку для транспорта QUIC. Добавление в работу транспортных протоколов сводится к простому добавлению параметров в конструктор хоста! Также обратите внимание, что мы регистрируем здесь все обработчики наших собственных протоколов: RegisterSayPreferAddr и RegisterPingPong. Наконец, мы регистрируем встроенную службуmDNS.

Теперь заглянем вdiscovery.go, где у нас находится настройка mDNS. Здесь, по сути, надо определить частоту широковещательной рассылки mDNS и строковый идентификатор, который в нашем случае не требуется и потому пустой. Последний шаг здесь - регистрация обработки уведомленияdiscovery.Notifee, которая будет вызываться всякий раз, когда mDNS запускает обнаружение пиров, предоставляя нам их информацию. Логика у нас тут будеттакая:

  1. Если мы уже знаем об этом узле - ничего не делаем; мы уже играли в пинг-понг. Иначе же

  2. открываем поток нашего протокола SayPreferAddr, чтобы узнать у обнаруженного узла, по какому адресу (addr) он предпочитает играть в пинг-понг. Ну, и наконец

  3. добавляем адрес узла в нашу адресную книгу, закрываем текущее соединение с ним и запускаем наш второй протокол PingPong, который повторно подключится к узлу, используя его предпочитаемый адрес (который мы добавили на предыдущем шаге).

Наконец, вpingpong.goмы можем увидеть упомянутый ранее метод RegisterPingPong, вызываемый из main.go, и еще два метода:

  • Handler: этот метод будет вызываться, когда сторонний узел зовёт нас играть в PingPong. Вы можете думать о Handler как об обработчике HTTP REST. В этом обработчике мы получаемStream, реализующий io.ReadWriteCloser, из которого мы можем запускать наш протокол для отправки и получения информации, чтобы делать что-то полезное.

  • playPingPong: Это другая сторона медали; клиент запускает новыйStreamдля внешнего узла для запуска протокола PingPong.

Как видите, реализация своих протоколов довольно-таки проста и полностью абстрагирована от других, инфраструктурных задач. Единственное, о чем нам нужно позаботиться, так это о написании полезного для нашего проекта прикладного кода. Заметьте также, что добавление нового протокола, например, вsaymyaddr.go, очень похоже на pingpong.go.

Если вас интересуют детали кода в подробностях, читайте комментарии, указывающие на некоторые важные вещи, которые вам, вероятно, следует учитывать при использовании libp2p.

Чтобы протестировать нашу демо-программу, можно открыть два терминала и просто запустить: go run * .go , go run * .go -quic или их комбинации. Ниже вы можете видеть иллюстрацию с двумя терминалами, работающими с флагом -quic:

Обратите внимание, как, сразу после запуска, узел в нижнем терминале обнаруживает узел в верхнем, ибо mDNS немедленно находит существующие узлы. Затем "нижний" сразу переходит к игре в пинг-понг. "Верхний" узел тоже, но с определённой задержкой (из-за 5-секундного интервала, который мы установили для нашей службы mDNS) обнаружит "нижний" собственными средствами, что, в свою очередь, вызоветновуюигру в пинг-понг.

Заметим также, что когда каждая из сторон отправляет сообщение PingPong или отвечает на него, она выдает полную информацию о мульти-адресе (multiaddr), на который обращается, где можно увидеть, что используется протокол QUIC. Попробуйте запустить этот примербезфлага -quic для обоих партнеров и посмотрите, как это повлияет на результат!

И ещё отметим для себя, что если запустить один терминал с флагом -quic, а другой - без него, последний партнер не сможет играть в PingPong с первым, потому что у него не включена поддержка QUIC. В более реалистичном сценарии вы могли бы использоватьвседоступные вам адреса узла-собеседника, чтобы иметь больше возможностей общаться в рамках базового транспортного протокола, которыйобапонимают. Изящно, не правда ли?

Что дальше?

Важным качеством приложения является его пригодность для дальнейшего развития. В p2p-проектах в основе прикладной логики находится сетевое взаимодействие. Если однажды в будущем мы захотим модернизировать наш протокол PingPong добавлением новых функций или возможностей, мы должны учитывать, что некоторые узлы будут по-прежнему работать со старой версией протокола! Это звучит как ночной кошмар, однако отставить бояться, мы с этим справились. И тут надо приметить следующий фрагмент кода из pingpong.go:

КОД:ВДЕЛИТЬ ВСЁ

const (    protoPingPong = "/pingpong/1.0.0")...func RegisterPingPong(h host.Host) {    pp := &pingPong{host: h}    // Здесь мы регистрируем наш _pingpong_ протокол.    // В будущем, если решите достраивать/исправлять ваш протокол,    // вы можете либо делать текущую версию обратно совместимой,    // либо зарегистрировать новый обработчик,     // с указанием новой главной версии протокола.    // Если хотите, можете также использовать логику semver,    // см. здесь: http://bit.ly/2YaJsJr    h.SetStreamHandler(protoPingPong, pp.Handler)}

Комментарии прекрасно всё объясняют.

Другой важный вопрос связан с механизмом обнаружения других узлов, в нашем случае это mDNS. Этот протокол делает свою работу в локальных сетях, но как насчет обнаружения пиров в Интернете? Позднее вы можете добавить в своё приложениеKademlia DHTили использовать один из механизмовpubsub- также, чтобы находить новые узлы.

Что здесь особо ценно, так это то, что будущие доработки не заставят вас переписывать существующую реализацию.Лёгкость изменения приложения - признак хорошего дизайна, а это значит, что libp2p также помогает выстраивать наш код в верном ключе.Спасибо за это разработчикам libp2p!

Заключительные слова

Libp2p имеет множество встроенных инструментов для решениябольшинствасложных проблем, с которыми вы можете столкнуться в p2p-системах. Рекомендуем вам заглянуть в разделреализацийна официальной веб-странице libp2p, чтобы узнать, что уже доступно и что ещё в работе. Всё быстро меняется, поэтому неплохо быть в курсе всего самого нового и лучшего.

Важно: имейте также в виду, если вы используете libp2p с включенными Go-модулями, вам нужно явно указывать тег версии в go get, поскольку иначе вы можете получить не то, что ожидали по умолчанию. Больше информации об этом вы можете найти в секцииUsagereadme-файла go-libp2p.

Надеемся, что вам понравился наш игрушечный проект, и надеемся, что он вселит в вас уверенность в том, что писать p2p-приложения не так сложно, как могло бы показаться! На самом-то деле, это может быть довольно кайфово и вдохновляюще! Если вам по нраву сей материал, присоединяйтесь к нам нанашем канале в Slack, чтобы пообщаться на тему p2p-протоколов, или подписывайтесь на нас вTwitter, чтобы узнавать о самых свежих и славных разработкахTextile. Ну, или хотя бы гляньте некоторыедругие наши статьи и демонстрации, чтобы полнее прочувствовать, что возможно в этом захватывающем мире приложений P2P!

Автор оригинального текста:Ignacio Hagopian

Перевод: Алексей Силин (StarVer)

Источник: habr.com
К списку статей
Опубликовано: 25.04.2021 14:23:00
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Децентрализованные сети

Open source

Go

Распределенные системы

Ipfs

Libp2p

P2p

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru