Sumário
- libp2p gossipsub
- Contexto
- Descoberta de pares libp2p
- Estruturação
- Kademlia DHT
- Descoberta de Pares
- Subiscritor gossipsub
- Executar aplicativo
- instalar dependências golang
- Referências
libp2p gossipsub
Contexto
No meu post anterior, discuti sobre a construção de um sistema de publicador/assinante (pubsub) ponto a ponto com libp2-pubsub
. A implementação feita com gossipsub
do go-libp2p-pubsub
livraria. A principal preocupação que tive com essa aplicação é que ela não pode descobrir os pares por trás do NAT. Isso significa que ele não pode se conectar aos pares por trás do NAT. Por exemplo, se eu executar um par pubsub na minha máquina local e outro na nuvem AWS. As mensagens do gossipsub não são entregues entre esses pares. A razão é multicast DNS[mDNS]
algoritmo de descoberta de pares que usei. Para superar esse problema de descoberta de pares, podemos usar a abordagem baseada na Tabela de Hash Distribuída ([DHT]
. Neste post vou discutir sobre a descoberta de pares libp2p-pubsub com DHT. Todos os códigos-fonte relacionados a este post estão disponíveis em gitlab. Por favor copie este repositório e continue com o post.
Descoberta de pares libp2p
Depois de criar um host, como os hosts vão descobrir uns aos outros? Existem duas opções disponíveis na libp2p: DNS multicast
(mDNS)
e uma Tabela de Hash Distribuída
.(mDNS)
envia um multicast UDP
mensagem na porta 5353
, anunciando sua presença. Isso é usado, por exemplo, pelo Apple Bonjour ou por impressoras. Funciona em redes locais, mas é claro que não funciona na internet.Um DHT
pode ser usado para descobrir pares também. Quando um par se junta a um DHT, ele pode usar o armazenamento de valor-chave para anunciar sua presença e encontrar outros pares na rede. A chave usada para anunciar sua presença é chamada de ponto de encontro.
Existem duas diferenças principais entre usar mDNS
ou um DHT
para descobrir pares. O primeiro que já mencionei, mDNS
não funciona na internet, onde um DHT
funciona. A segunda diferença é que um DHT
requer nós de inicialização. Outros nós podem ingressar na rede conectando-se a um nó de inicialização e, em seguida, descobrir o restante da rede.
Estruturação
Eu usei a biblioteca libp2p-pubsub
para construir o Librumchain
que é um armazenamento blockchain leve e altamente escalável. Em Librumchain
existe um grupo de consenso central que roda em nós baseados em nuvem com consenso Proof-of-Authority
. Os nós de borda projetados para serem executados em nós leves baseados em Raspberry-Pi
. O grupo de consenso principal gera blocos e os armazena no IPFS-Cluster
(IPFS-Cluster
foi usado como armazenamento de blocos). As informações de bloco geradas (por exemplo, o hash IPFS
do bloco) serão publicadas nos nós de borda Raspberry-Pi via libp2p gossipsub
. A figura a seguir descreve a arquitetura do Librumchain com Grupo de consenso central
, IPFS-Cluster
e nós de borda Raspberry-Pi
.
Em meu post anterior, desenvolvi este aplicativo com libp2p gossipsub usando o método de descoberta de pares mDNS
. Só funcionava em rede local e não funcionava com os pares na internet pública. Então eu incorporei o método de descoberta de pares DHT
para resolver esse problema. No aplicativo pubsub, o par do publicador recebe mensagens da linha de comando e as envia para um tópico chamado librum
. Em seguida, os assinantes desse tópico do librum
recebem os dados via gossipsub ponto a ponto. Os pares descobrem outros pares na rede usando o método DHT
. Assim, pode funcionar pela internet. Esta é uma versão simplificada do sistema pubsub do Librumchain.
Kademlia DHT
libp2p DHT
usa Kademlia DHT
. No programa a seguir, criei pares de inicialização registrados no Kademlia DHT
no DHT
. Uma coisa importante a notar aqui está na linha 17-18
. Adicionou uma opção para instruir o par que, caso nenhum par de inicialização seja fornecido, ele deve entrar no modo servidor. No modo servidor, ele atua como um nó de inicialização, permitindo que outros pares se juntem a ele. Às vezes, você pode precisar habilitar o UPnP
na configuração do roteador para que isso funcione. Caso você queira se juntar ao Kademlia DHT
global da libp2p, você pode usar os pares de inicialização em dht.DefaultBootstrapPeers
.
package main
import (
"context"
"log"
"sync"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-kad-dht"
"github.com/multiformats/go-multiaddr"
)
func NewDHT(ctx context.Context, host host.Host, bootstrapPeers []multiaddr.Multiaddr) (*dht.IpfsDHT, error) {
var options []dht.Option
// se não houver pares de bootstrap, este par age como um nó de bootstrap
// outros pares podem usar este endereço ipfs de par dht
if len(bootstrapPeers) == 0 {
options = append(options, dht.Mode(dht.ModeServer))
}
kdht, err := dht.New(ctx, host, options...)
if err != nil {
return nil, err
}
if err = kdht.Bootstrap(ctx); err != nil {
return nil, err
}
var wg sync.WaitGroup
for _, peerAddr := range bootstrapPeers {
peerinfo, _ := peer.AddrInfoFromP2pAddr(peerAddr)
wg.Add(1)
go func() {
defer wg.Done()
if err := host.Connect(ctx, *peerinfo); err != nil {
log.Printf("Error while connecting to node %q: %-v", peerinfo, err)
} else {
log.Printf("Connection established with bootstrap node: %q", *peerinfo)
}
}()
}
wg.Wait()
return kdht, nil
}
I3.97KL0LDI1.76KwhoissourceRank8.43MPIN0Summary reportDiagnosisDensity00n/a
Descoberta de Pares
Então eu criei outro programa para descobrir os pares na rede usando o protocolo de descoberta de pares DHT
e rendezvous
criado anteriormente. O protocolo Rendezvous
destina-se a fornecer um mecanismo leve para descoberta generalizada de pares. Ele pode ser usado para fins de inicialização, descoberta de pares em tempo real, roteamento específico do aplicativo e assim por diante. Qualquer nó que implemente o protocolo de rendezvous
pode atuar como um ponto de encontro, permitindo a descoberta de pares relevantes de forma descentralizada.
Aqui, a função FindPeers()
fornece todos os pares que foram descobertos no ponto de encontro. Como o próprio nó também faz parte dos pares descobertos, ele precisa ser filtrado. Para todos os outros pares , verifique se eles já estão conectados, caso contrário, disque-os
para criar uma conexão.
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-discovery"
dht "github.com/libp2p/go-libp2p-kad-dht"
)
func Discover(ctx context.Context, h host.Host, dht *dht.IpfsDHT, rendezvous string) {
var routingDiscovery = discovery.NewRoutingDiscovery(dht)
discovery.Advertise(ctx, routingDiscovery, rendezvous)
ticker := time.NewTicker(time.Second * 1)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
peers, err := discovery.FindPeers(ctx, routingDiscovery, rendezvous)
if err != nil {
log.Fatal(err)
}
for _, p := range peers {
if p.ID == h.ID() {
continue
}
if h.Network().Connectedness(p.ID) != network.Connected {
_, err = h.Network().DialPeer(ctx, p.ID)
fmt.Printf("Connected to peer %s\n", p.ID.Pretty())
if err != nil {
continue
}
}
}
}
}
}
Publicador Gossipsub
Existem dois tipos de pares de publicador na rede, pares de inicialização (pares públicos) e pares normais (pares por trás do NAT). Como mencionei acima, as funções de inicialização do DHT
adicionam uma opção para instruir o par a agir como um nó de inicialização, permitindo que outros pares se juntem a ele. Para manter as coisas simples, criei esses dois publicadores em programas separados (você pode criá-lo facilmente em um único programa). Um publicador criou uma lista de inicialização vazia, então ela atua como um par de inicialização. Outro criado com o endereço IPFS do par de inicialização. A seguir está a implementação golang dos publicadores. Eu adicionei comentários para descrever a função de cada linha no código. O Publicador recebe mensagens ouvindo a linha de comando e publica no tópico.
package main
import (
"bufio"
"context"
"fmt"
"os"
"time"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/peer"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/libp2p/go-libp2p/p2p/discovery/mdns"
"github.com/multiformats/go-multiaddr"
)
// DiscoveryInterval é a frequência com que re-publicamos nossos registros mDNS.
const DiscoveryInterval = time.Hour
// DiscoveryServiceTag é usado em nossos anúncios mDNS para descobrir outros pares.
const DiscoveryServiceTag = "librum-pubsub"
func main() {
ctx := context.Background()
// Cria um novo Host libp2p que escuta em uma porta TCP aleatória
// Podemos especificar uma porta como /ip4/0.0.0.0/tcp/3326
// we can specify port like /ip4/0.0.0.0/tcp/3326
host, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0"))
if err != nil {
panic(err)
}
// ver os detalhes do host e do endereço
fmt.Printf("host ID %s\n", host.ID().Pretty())
fmt.Printf("following are the assigned addresses\n")
for _, addr := range host.Addrs() {
fmt.Printf("%s\n", addr.String())
}
fmt.Printf("\n")
// cria um novo serviço PubSub usando o roteador GossipSub
gossipSub, err := pubsub.NewGossipSub(ctx, host)
if err != nil {
panic(err)
}
// Configura o DHT com pares de descoberta vazios
// então este será um pares de descoberta para outros
// Este par deve ser executado na nuvem (com endereço ip público)
discoveryPeers := []multiaddr.Multiaddr{}
dht, err := NewDHT(ctx, host, discoveryPeers)
if err != nil {
panic(err)
}
// Configura a descoberta de pares
go Discover(ctx, host, dht, "librum")
// setup local mDNS discovery
// Configura a descoberta de mDNS local
if err := setupDiscovery(host); err != nil {
panic(err)
}
// junta ao tópico pubsub chamado librum
room := "librum"
topic, err := gossipSub.Join(room)
if err != nil {
panic(err)
}
// Cria o publicador(editor)
publish(ctx, topic)
}
// start publisher to topic
// inicia o editor no tópico
func publish(ctx context.Context, topic *pubsub.Topic) {
for {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
fmt.Printf("enter message to publish: \n")
msg := scanner.Text()
if len(msg) != 0 {
// Publica a mensagem no tópico
bytes := []byte(msg)
topic.Publish(ctx, bytes)
}
}
}
}
// O discoveryNotifee é notificado quando encontrado um novo par via descoberta de mDNS
type discoveryNotifee struct {
h host.Host
}
// HandlePeerFound se conecta a pares descobertos via mDNS. Assim que estiverem conectados,
// o sistema PubSub começará a interagir automaticamente com eles se eles também
// suportam PubSub.
func (n *discoveryNotifee) HandlePeerFound(pi peer.AddrInfo) {
fmt.Printf("discovered new peer %s\n", pi.ID.Pretty())
err := n.h.Connect(context.Background(), pi)
if err != nil {
fmt.Printf("error connecting to peer %s: %s\n", pi.ID.Pretty(), err)
}
}
// setupDiscovery cria um serviço de descoberta mDNS e o anexa ao Host libp2p.
// Isso nos permite descobrir automaticamente pares na mesma LAN e nos conectar a eles.
func setupDiscovery(h host.Host) error {
// Configura a descoberta de mDNS para encontrar pares locais
s := mdns.NewMdnsService(h, DiscoveryServiceTag, &discoveryNotifee{h: h})
return s.Start()
}
package main
import (
"bufio"
"context"
"fmt"
"os"
"time"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/peer"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/libp2p/go-libp2p/p2p/discovery/mdns"
"github.com/multiformats/go-multiaddr"
)
// DiscoveryInterval é a frequência com que re-publicamos nossos registros mDNS.
const DiscoveryInterval = time.Hour
// DiscoveryServiceTag é usado em nossos anúncios mDNS para descobrir outros pares.
const DiscoveryServiceTag = "librum-pubsub"
func main() {
ctx := context.Background()
// Cria um novo Host libp2p que escuta em uma porta TCP aleatória
// Podemos especificar uma porta como /ip4/0.0.0.0/tcp/3326
// we can specify port like /ip4/0.0.0.0/tcp/3326
host, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0"))
if err != nil {
panic(err)
}
// ver os detalhes do host e do endereço
fmt.Printf("host ID %s\n", host.ID().Pretty())
fmt.Printf("following are the assigned addresses\n")
for _, addr := range host.Addrs() {
fmt.Printf("%s\n", addr.String())
}
fmt.Printf("\n")
// cria um novo serviço PubSub usando o roteador GossipSub
gossipSub, err := pubsub.NewGossipSub(ctx, host)
if err != nil {
panic(err)
}
// Configura o DHT com pares de descoberta vazios
// então este será um pares de descoberta para outros
// Este par deve ser executado na nuvem (com endereço ip público)
discoveryPeers := []multiaddr.Multiaddr{}
dht, err := NewDHT(ctx, host, discoveryPeers)
if err != nil {
panic(err)
}
// Configura a descoberta de pares
go Discover(ctx, host, dht, "librum")
// setup local mDNS discovery
// Configura a descoberta de mDNS local
if err := setupDiscovery(host); err != nil {
panic(err)
}
// junta ao tópico pubsub chamado librum
room := "librum"
topic, err := gossipSub.Join(room)
if err != nil {
panic(err)
}
// Cria o publicador(editor)
publish(ctx, topic)
}
// start publisher to topic
// inicia o editor no tópico
func publish(ctx context.Context, topic *pubsub.Topic) {
for {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
fmt.Printf("enter message to publish: \n")
msg := scanner.Text()
if len(msg) != 0 {
// Publica a mensagem no tópico
bytes := []byte(msg)
topic.Publish(ctx, bytes)
}
}
}
}
// O discoveryNotifee é notificado quando encontrado um novo par via descoberta de mDNS
type discoveryNotifee struct {
h host.Host
}
// HandlePeerFound se conecta a pares descobertos via mDNS. Assim que estiverem conectados,
// o sistema PubSub começará a interagir automaticamente com eles se eles também
// suportam PubSub.
func (n *discoveryNotifee) HandlePeerFound(pi peer.AddrInfo) {
fmt.Printf("discovered new peer %s\n", pi.ID.Pretty())
err := n.h.Connect(context.Background(), pi)
if err != nil {
fmt.Printf("error connecting to peer %s: %s\n", pi.ID.Pretty(), err)
}
}
// setupDiscovery cria um serviço de descoberta mDNS e o anexa ao Host libp2p.
// Isso nos permite descobrir automaticamente pares na mesma LAN e nos conectar a eles.
func setupDiscovery(h host.Host) error {
// Configura a descoberta de mDNS para encontrar pares locais
s := mdns.NewMdnsService(h, DiscoveryServiceTag, &discoveryNotifee{h: h})
return s.Start()
}
Subiscritor gossipsub
Semelhante aos publicadores, criei dois tipos de pares de assinante para manter as coisas simples, pares de inicialização (pares públicos) e pares normais (pares por trás do NAT). Um assinante criou uma lista de inicialização vazia, então ele atua como um par de inicialização. Outro criado com o endereço IPFS do par de inicialização. A seguir está a implementação golang de assinantes. Eu adicionei comentários para descrever a função de cada linha no código.
package main
import (
"context"
"fmt"
"time"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/peer"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/libp2p/go-libp2p/p2p/discovery/mdns"
"github.com/multiformats/go-multiaddr"
)
// O DiscoveryInterval é a frequência com que re-publicamos nossos registros mDNS.
const DiscoveryInterval = time.Hour
// O DiscoveryServiceTag é usado em nossos anúncios mDNS para descobrir outros pares.
const DiscoveryServiceTag = "librum-pubsub"
func main() {
ctx := context.Background()
// cria um novo Host libp2p que escuta em uma porta TCP aleatória
host, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/7654"))
if err != nil {
panic(err)
}
// ver detalhes e endereços do host
fmt.Printf("host ID %s\n", host.ID().Pretty())
fmt.Printf("following are the assigned addresses\n")
for _, addr := range host.Addrs() {
fmt.Printf("%s\n", addr.String())
}
fmt.Printf("\n")
// Cria um novo serviço PubSub usando o roteador GossipSub
gossipSub, err := pubsub.NewGossipSub(ctx, host)
if err != nil {
panic(err)
}
// Configura o DHT com pares de descoberta vazios
// Então este será um ponto de descoberta para outros
// Este peer deve ser executado na nuvem (com endereço ip público)
discoveryPeers := []multiaddr.Multiaddr{}
dht, err := NewDHT(ctx, host, discoveryPeers)
if err != nil {
panic(err)
}
// Configura a descoberta de pares
go Discover(ctx, host, dht, "librum")
// Junta-se ao tópico pubsub chamado librum
room := "librum"
topic, err := gossipSub.Join(room)
if err != nil {
panic(err)
}
// subscrever-se no topico
subscriber, err := topic.Subscribe()
if err != nil {
panic(err)
}
subscribe(subscriber, ctx, host.ID())
}
// inicia o assinante do tópico
func subscribe(subscriber *pubsub.Subscription, ctx context.Context, hostID peer.ID) {
for {
msg, err := subscriber.Next(ctx)
if err != nil {
panic(err)
}
// considera apenas as mensagens entregues por outros pares
if msg.ReceivedFrom == hostID {
continue
}
fmt.Printf("got message: %s, from: %s\n", string(msg.Data), msg.ReceivedFrom.Pretty())
}
}
// discoveryNotifee é notificado quando encontramos um novo ponto via descoberta de mDNS
type discoveryNotifee struct {
h host.Host
}
// HandlePeerFound se conecta os pares descobertos via mDNS. Assim que estiverem conectados,
// O sistema PubSub começará a interagir automaticamente com eles se eles também
// suportem PubSub.
func (n *discoveryNotifee) HandlePeerFound(pi peer.AddrInfo) {
fmt.Printf("discovered new peer %s\n", pi.ID.Pretty())
err := n.h.Connect(context.Background(), pi)
if err != nil {
fmt.Printf("error connecting to peer %s: %s\n", pi.ID.Pretty(), err)
}
}
// setupDiscovery cria um serviço de descoberta mDNS e o anexa ao Host libp2p.
// Isso nos permite descobrir automaticamente pares na mesma LAN e nos conectar a eles.
func setupDiscovery(h host.Host) error {
// configura a descoberta de mDNS para encontrar pontos locais
s := mdns.NewMdnsService(h, DiscoveryServiceTag, &discoveryNotifee{h: h})
return s.Start()
}
package main
import (
"context"
"fmt"
"time"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/peer"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/libp2p/go-libp2p/p2p/discovery/mdns"
"github.com/multiformats/go-multiaddr"
)
// O DiscoveryInterval é a frequência com que re-publicamos nossos registros mDNS.
const DiscoveryInterval = time.Hour
// O DiscoveryServiceTag é usado em nossos anúncios mDNS para descobrir outros pares.
const DiscoveryServiceTag = "librum-pubsub"
func main() {
ctx := context.Background()
// cria um novo Host libp2p que escuta em uma porta TCP aleatória
host, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/7654"))
if err != nil {
panic(err)
}
// ver detalhes e endereços do host
fmt.Printf("host ID %s\n", host.ID().Pretty())
fmt.Printf("following are the assigned addresses\n")
for _, addr := range host.Addrs() {
fmt.Printf("%s\n", addr.String())
}
fmt.Printf("\n")
// cria um novo serviço PubSub usando o roteador GossipSub
gossipSub, err := pubsub.NewGossipSub(ctx, host)
if err != nil {
panic(err)
}
// endereço ipfs dos pares de descoberta
// eu adicionei um par aqui, você pode adicionar vários pares de disovery
multiAddr, err := multiaddr.NewMultiaddr("/ip4/20.228.145.221/tcp/7654/p2p/QmPMFJUzfB1LrxksmpS75QNwtmN8TCEcMvSezL3V9hp8a4")
if err != nil {
panic(err)
}
println(multiAddr)
// configura DHT com servidor de descoberta
// este peer pode rodar atrás do nat(com endereço ip privado)
discoveryPeers := []multiaddr.Multiaddr{multiAddr}
dht, err := NewDHT(ctx, host, discoveryPeers)
if err != nil {
panic(err)
}
// configura a descoberta de pares
go Discover(ctx, host, dht, "librum")
// junta-se ao tópico pubsub chamado librum
room := "librum"
topic, err := gossipSub.Join(room)
if err != nil {
panic(err)
}
//subscrever-se no tópico
subscriber, err := topic.Subscribe()
if err != nil {
panic(err)
}
subscribe(subscriber, ctx, host.ID())
}
// inicia o assinante do tópico
func subscribe(subscriber *pubsub.Subscription, ctx context.Context, hostID peer.ID) {
for {
msg, err := subscriber.Next(ctx)
if err != nil {
panic(err)
}
// considera apenas mensagens entregues por outros pares
if msg.ReceivedFrom == hostID {
continue
}
fmt.Printf("got message: %s, from: %s\n", string(msg.Data), msg.ReceivedFrom.Pretty())
}
}
// O discoveryNotifee é notificado quando encontramos um novo peer via descoberta de mDNS
type discoveryNotifee struct {
h host.Host
}
// HandlePeerFound se conecta a pares descobertos via mDNS. Assim que estiverem conectados,
// o sistema PubSub começará a interagir automaticamente com eles se eles também
// suparterem para o PubSub.
func (n *discoveryNotifee) HandlePeerFound(pi peer.AddrInfo) {
fmt.Printf("discovered new peer %s\n", pi.ID.Pretty())
err := n.h.Connect(context.Background(), pi)
if err != nil {
fmt.Printf("error connecting to peer %s: %s\n", pi.ID.Pretty(), err)
}
}
// setupDiscovery cria um serviço de descoberta mDNS e o anexa ao Host libp2p.
// Isso nos permite descobrir automaticamente pares na mesma LAN e nos conectar a eles.
func setupDiscovery(h host.Host) error {
// configura a descoberta de mDNS para encontrar pares locais
s := mdns.NewMdnsService(h, DiscoveryServiceTag, &discoveryNotifee{h: h})
return s.Start()
}
Executar aplicativo
A seguir está a maneira de construir e executar a aplicação. Eu já executei a inicialização do publicador e do assinante na nuvem AWS com IP público.. Publicador normal e assinante funcionam em máquina local. Os dados de publicação estarão disponíveis para os assinantes em tempo real. A comunicação de gossipsub acontece com sucesso através da Internet, utilizando o método de descoberta por pares DHT
.
instalar dependências golang
go mod init
go mod tidy
---
# construir editores e assinantes locais no diretório ./build
# executar na maquina local
go build -o build/subscriber src/subsciber.go src/dht.go src/discover.go
go build -o build/publisher src/publisher.go src/dht.go src/discover.go
---
# construir editor e assinante de bootstrap ./diretório build
# rodar na maquina local
go build -o build/subscriberd src/bootstrap-subsciber.go src/dht.go src/discover.go
go build -o build/publisherd src/bootstrap-publisher.go src/dht.go src/discover.go
---
# rodar o iniciador de subscrição ( no terminal 1)
# rodar na maquina aws
# coloca o endereço ipfs do par como o endereço do peer de descoberta no local dos editores e assinantes
./build/subscriberd
# executa o assinante local (no terminal 2)
# executa no local na maquina
./build/sbscriber
# executa o assinante local (no terminal 3)
# executa no local na maquina
./build/publisher
Segue a saída. A primeira guia do terminal é o par de assinante de inicialização que é executado na máquina AWS. A segunda guia do terminal executa o par de assinante local. A terceira guia do terminal executa o par do publicador local. Ao publicar mensagens do publicador local, elas estarão disponíveis no assinante local e nos assinantes da AWS.
Referências
1. https://ldej.nl/post/building-an-echo-application-with-libp2p/
2. https://gist.github.com/upperwal/38cd0c98e4a6b34c061db0ff26def9b9#file-libp2p_chat_bootstrapping-md
3. https://github.com/libp2p/go-libp2p/blob/master/examples/chat-with-rendezvous/chat.go
4. https://codethechange.stanford.edu/guides/guide_kademlia.html
5. https://github.com/libp2p/js-libp2p-kad-dht
Este artigo foi escrito por λ.eranga, e traduzido por AIengineer13.
Encontre o artigo original aqui.
Abrace a oportunidade de elevar sua jornada de desenvolvimento para um nível superior. Pares libp2p é apenas o começo; os builds incríveis da WEB3DEV representam a chave de entrada para o emocionante cenário web3. 🚀🧑💻
Não perca tempo, 👉inscreva-se👈 agora mesmo e comece a desbravar o universo Blockchain!
Seja também WEB3DEV!
Oldest comments (0)