Разница между мультиплексом и многопоточностью - PullRequest
1 голос
/ 22 марта 2019

В чем разница между многопоточностью (yamux, multistream-select, ..) и мультиплексом (mplex)? Я хотел бы использовать одно TCP-соединение для RPC, HTTP и т. Д. (Один клиент находится за брандмауэром), например:

conn = tcp.connect("server.com:1111")
conn1, conn2 = conn.split()

stream1 = RPC(conn1)
stream2 = WebSocket(conn2)
..

// received packets tagged for conn1 is forwarded to stream1
// received packets tagged for conn2 is forwarded to stream2
// writing to stream1 tags the packets for conn1
// writing to stream2 tags the packets for conn2

Какой из них подходит для этого случая?

1 Ответ

2 голосов
/ 22 марта 2019

Краткий ответ: mplex и yamux оба являются потоковыми мультиплексорами (или потоковыми мультиплексорами) и отвечают за чередование нескольких «логических потоков» по ​​одному «необработанному» соединению (например, TCP). Многопоточный режим используется для определения , какой протокол следует использовать при отправке / получении данных через поток, а многопотоковый выбор позволяет партнерам согласовывать , какие протоколы поддерживаются каждым концом, и, как мы надеемся, согласится на одном, чтобы использовать.

Длинный ответ:

Потоковое мультиплексирование - это интерфейс с несколькими реализациями. «Базовый» потоковый мультиплексор называется mplex - libp2p-специфичный протокол с реализациями в javascript , go и rust .

Потоковые мультиплексоры являются «подключаемыми», что означает, что вы добавляете их поддержку, вставляя модуль и настраивая свое приложение libp2p для их использования. Данное приложение libp2p может поддерживать несколько мультиплексоров одновременно, поэтому, например, вы можете использовать yamux по умолчанию, но также поддерживать mplex для связи с пирами, которые не поддерживают yamux.

Несмотря на то, что подобная гибкость великолепна, это также означает, что нам нужен способ выяснить, какой потоковый мультиплексор использовать для любого конкретного соединения. Вот тут и вступают многопоточные и многопотоковые.

Multistream (несмотря на название) не имеет прямого отношения к мультиплексированию потоков. Вместо этого он действует как «заголовок» для потока двоичных данных, который контекстуализирует поток с идентификатором протокола. Тесно связанный протокол многопотокового выбора использует идентификаторы протокола Multistream для согласования того, какие протоколы использовать для «следующей фазы» связи.

Итак, чтобы согласовать, какой потоковый мультиплексор использовать, мы используем multistream-select.

Вот пример мультипотокового выбора туда-сюда:

/multistream/1.0.0 <- dialer says they'd like to use multistream 1.0.0
/multistream/1.0.0 -> listener echoes back to indicate agreement
/secio/1.0.0       <- dialer wants to use secio 1.0.0 for encryption
/secio/1.0.0       -> listener agrees

* secio handshake omitted. what follows is encrypted via secio: *

/mplex/6.7.0       <- dialer would like to use mplex 6.7.0 for stream multiplexing
/mplex/6.7.0       -> listener agrees

Это простой случай, когда обе стороны обо всем договариваются - например, слушатель не поддерживал /mplex/6.7.0, он мог ответить na (недоступно), а номеронабиратель мог либо попробовать другой протокол, запросить список поддерживаемых протоколов, отправив ls, либо сдаться.

В приведенном выше примере обе стороны договорились о mplex, поэтому будущая связь через открытое соединение будет зависеть от семантики mplex.

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

Вместо этого компонент libp2p, называемый «switch» (также называемый «роем» в некоторых реализациях), управляет состоянием набора / прослушивания для приложения. Коммутатор обрабатывает многопотоковый процесс согласования и «скрывает» детали того, какой конкретный потоковый мультиплексор используется от остальной части стека libp2p.

Как разработчик libp2p, вы обычно звоните другим партнерам, используя интерфейс коммутатора, который даст вам поток для чтения и записи. Внутри коммутатора коммутатор найдет соответствующий транспорт (например, TCP / websockets) и использует функцию множественного выбора для согласования шифрования и мультиплексирования потоков. Если у вас уже есть открытое соединение с удаленным одноранговым узлом, коммутатор просто использует существующее соединение и открывает поверх него другой мультиплексированный поток, вместо того, чтобы начинать с нуля.

То же самое относится и к прослушиванию соединений - вы даете коммутатору идентификатор протокола и функцию обработчика потока, и он будет обрабатывать процесс мультиплексирования и согласования для вас.

Наша документация находится в стадии разработки, но в https://docs.libp2p.io есть некоторая информация, которая может помочь прояснить, особенно концептуальный документ по транспортам и глоссарий . Вы также можете найти ссылки на пример кода .

Улучшение документации для libp2p - это мой основной квест на данный момент, поэтому, пожалуйста, не стесняйтесь сообщать о проблемах на https://github.com/libp2p/docs, чтобы сообщить мне, какие ваши самые важные недостающие фрагменты.

...