Skip to content

Consul

Consul è una soluzione che consente ai team di gestire in modo sicuro le connessioni di rete tra servizi e attraverso ambienti multi-piattaforma e multi-cloud. Fornisce funzionalità come scoperta dei servizi, service mesh, governance del traffico e aggiornamenti automatici dell'infrastruttura di rete.

Documentazione ufficiale: Consul by HashiCorp

Repository open source: hashicorp/consul

Consul è uno strumento open source per la scoperta e registrazione dei servizi sviluppato da HashiCorp. Utilizza l'algoritmo di elezione Raft ed è scritto in Go, rendendolo molto leggero da distribuire. Consul ha le seguenti caratteristiche:

  • Scoperta dei servizi
  • Registrazione dei servizi
  • Health check
  • Archiviazione chiave-valore
  • Multi-datacenter

In realtà, Consul può fare più della semplice scoperta dei servizi; può anche essere utilizzato come centro di configurazione distribuito. Esistono molti altri strumenti open source simili come Zookeeper e Nacos, che non verranno trattati ulteriormente qui.

Installazione

Per Ubuntu, eseguire i seguenti comandi per installare tramite apt:

sh
$ wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
$ echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
$ sudo apt update && sudo apt install consul

In alternativa, è possibile scaricare dal sito ufficiale Install Consul il pacchetto di installazione corrispondente. Poiché Consul è sviluppato in Go, il pacchetto di installazione è un singolo file binario eseguibile, rendendo l'installazione molto semplice. Dopo un'installazione riuscita, eseguire il seguente comando per verificare la versione:

sh
$ consul version

Un output normale indica che non ci sono problemi:

Consul v1.16.1
Revision e0ab4d29
Build Date 2023-08-05T21:56:29Z
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)

Guida Rapida

Di seguito viene illustrato come configurare rapidamente un singolo nodo Consul. Generalmente, un singolo nodo viene utilizzato per i test durante lo sviluppo. Se un singolo nodo funziona correttamente, molto probabilmente anche un cluster multi-nodo funzionerà senza problemi. La configurazione di un singolo nodo è molto semplice e richiede solo un comando:

sh
$ consul agent -dev -bind=192.168.48.141 -data-dir=/tmp/consul -ui -node=dev01

L'output tipico è il seguente:

==> Starting Consul agent...
               Version: '1.16.1'
            Build Date: '2023-08-05 21:56:29 +0000 UTC'
               Node ID: 'be6f6b8d-9668-f7ff-8709-ed57c72ffdec'
             Node name: 'dev01'
            Datacenter: 'dc1' (Segment: '<all>')
                Server: true (Bootstrap: false)
           Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: 8502, gRPC-TLS: 8503, DNS: 8600)
          Cluster Addr: 192.168.48.141 (LAN: 8301, WAN: 8302)
     Gossip Encryption: false
      Auto-Encrypt-TLS: false
           ACL Enabled: false
     Reporting Enabled: false
    ACL Default Policy: allow
             HTTPS TLS: Verify Incoming: false, Verify Outgoing: false, Min Version: TLSv1_2
              gRPC TLS: Verify Incoming: false, Min Version: TLSv1_2
      Internal RPC TLS: Verify Incoming: false, Verify Outgoing: false (Verify Hostname: false), Min Version: TLSv1_2
==> Log data will now stream in as it occurs:
2023-08-25T17:23:33.763+0800 [DEBUG] agent.grpc.balancer: switching server: target=consul://dc1.be6f6b8d-9668-f7ff-8709-ed57c72ffdec/server.dc1 from=<none> to=<none>
2023-08-25T17:23:33.767+0800 [INFO]  agent.server.raft: initial configuration: index=1 servers="[{Suffrage:Voter ID:be6f6b8d-9668-f7ff-8709-ed57c72ffdec Address:192.168.48.141:8300}]"

Breve spiegazione dei parametri:

  • agent è il sottocomando, il comando principale di Consul. consul agent esegue un nuovo agente Consul. Ogni nodo è un agente.

  • dev è la modalità di esecuzione dell'agente. Esistono tre modalità: dev, client, server.

  • bind è l'indirizzo di comunicazione LAN, porta predefinita 8301. Generalmente questo valore è l'indirizzo interno del server.

  • advertise è l'indirizzo di comunicazione WAN, porta predefinita 8302. Generalmente questo valore è l'indirizzo esterno del server.

  • data-dir è la directory di archiviazione dei dati.

  • config-dir è la directory di archiviazione della configurazione. Consul leggerà tutti i file json nella directory.

  • bootstrap indica che il server corrente entra in modalità bootstrap e voterà per se stesso durante l'elezione Raft. Nel cluster, non può esserci più di un server in questa modalità.

  • bootstrap-expect è il numero previsto di server nel cluster. Finché non viene raggiunto il numero specificato, il cluster non inizierà l'elezione. Non può essere usato contemporaneamente a bootstrap.

  • retry-join dopo l'avvio dell'agente, continuerà a tentare di unirsi ai nodi specificati. Supporta anche i seguenti metodi di scoperta dei servizi:

    aliyun aws azure digitalocean gce hcp k8s linode mdns os packet scaleway softlayer tencentcloud triton vsphere
  • ui esegue l'interfaccia Web.

  • node è il nome del nodo di esecuzione e deve essere unico nel cluster.

TIP

Per ulteriori spiegazioni sui parametri dell'agente, consultare Agents - CLI Reference | Consul | HashiCorp Developer. Si noti che alcuni parametri sono disponibili solo nella versione Enterprise.

Dopo un'esecuzione riuscita, accedere a 127.0.0.1:8500 per visualizzare l'interfaccia Web.

L'icona di dev01 è una stella, indicando che è il nodo leader.

Per uscire, per consentire agli altri nodi di rilevare l'uscita del nodo corrente, non è consigliabile terminare forzatamente il processo. È possibile utilizzare il comando:

sh
consul leave

oppure

sh
consul force-leave

In alternativa, premere ctrl+c per consentire all'agente Consul di uscire correttamente.

Concetti

Questo è un diagramma di un cluster Consul, diviso in due parti: piano di controllo e piano dati. Consul è responsabile solo del piano di controllo, diviso in cluster di servizi e client. Il cluster di servizi è ulteriormente diviso in follower e leader. Complessivamente, il cluster Consul costituisce un datacenter. Di seguito vengono spiegati alcuni termini:

  • Agent (Agente): o più appropriatamente chiamato nodo. Ogni agente è un processo daemon in esecuzione prolungata che espone interfacce HTTP e DNS, responsabile dei controlli di integrità e della sincronizzazione dei servizi.
  • Server (Agente Server): come server Consul, le sue responsabilità includono partecipare all'elezione Raft, mantenere lo stato del cluster, rispondere alle query, scambiare dati con altri datacenter e inoltrare query ai leader e ad altri datacenter.
  • Client (Agente Client): rispetto al server, il client è senza stato. Non partecipa all'elezione Raft e il suo unico compito è inoltrare tutte le richieste al server. L'unica cosa a cui partecipa relativa al backend è il gossip forwarding LAN (LAN gossip pool).
  • Leader: il leader è a capo di tutti i server e può esserci solo un leader. Il leader viene eletto attraverso l'algoritmo di elezione Raft. Ogni leader ha un proprio mandato e durante il mandato, qualsiasi richiesta ricevuta dagli altri server deve essere inoltrata al leader, quindi i dati del leader sono i più tempestivi e aggiornati.
  • Gossip: Consul è costruito su Serf (un altro prodotto della stessa azienda) e utilizza il protocollo gossip, dedicato alla comunicazione casuale tra nodi, simile a UDP. Consul utilizza questo protocollo per notificarsi reciprocamente nel cluster di servizi.
  • Data Center (Datacenter): un cluster Consul all'interno di una rete LAN è chiamato datacenter. Consul supporta più datacenter e il metodo di comunicazione tra più datacenter è il WAN gossip.

TIP

Per ulteriori vocaboli e termini, consultare Glossary | Consul | HashiCorp Developer.

Nel cluster Consul, il numero di server dovrebbe essere strettamente controllato poiché sono direttamente coinvolti nel LAN gossip e WAN gossip, nell'elezione Raft e nell'archiviazione dei dati. Più server ci sono, maggiore è il costo di comunicazione. Il numero di client può essere maggiore senza problemi, poiché sono solo responsabili dell'inoltro e non partecipano all'elezione, occupando pochissime risorse. Nel cluster mostrato nel diagramma, i vari servizi si registrano nel server tramite client. Se un server si guasta, i client cercheranno autonomamente altri server disponibili.

Esempio di Configurazione del Cluster

Di seguito viene illustrato un semplice esempio di configurazione di un cluster Consul multi-nodo. Preparare prima quattro macchine virtuali:

Delle quattro macchine virtuali, tre sono server e una è client. Il consiglio ufficiale è che il numero di server dovrebbe essere preferibilmente dispari e almeno tre. Qui vm00-vm02 sono server e vm03 è client.

Per i server, eseguire il seguente comando per creare un agente server:

sh
consul agent -server -bind=vm_address -client=0.0.0.0 -data-dir=/tmp/consul/ -node=agent_name -ui

Per i client, eseguire il seguente comando per creare un agente client:

sh
consul agent -client=0.0.0.0  -bind=vm_address -data-dir=/tmp/consul/ -node=agent_name -ui

I comandi eseguiti sono rispettivamente:

sh
# vm00
consul agent -server -bind=192.168.48.138 -client=0.0.0.0 -data-dir=/tmp/consul/ -node=agent01 -ui -bootstrap

# vm01
consul agent -server -bind=192.168.48.139 -client=0.0.0.0 -data-dir=/tmp/consul/ -node=agent02 -ui -retry-join=192.168.48.138

# vm02
consul agent -server -bind=192.168.48.140 -client=0.0.0.0 -data-dir=/tmp/consul/ -node=agent03 -ui -retry-join=192.168.48.138

# vm03
consul agent -bind=192.168.48.140 -client=0.0.0.0 -data-dir=/tmp/consul/ -node=agent03 -ui -retry-join=192.168.48.138

Spiegazione di alcuni parametri:

  • client: 0.0.0.0 accetta richieste da tutte le origini. Se è presente solo il parametro client senza il parametro server, l'agente funzionerà in modalità client.

Dopo che tutti gli agenti sono in esecuzione, la funzione di retry-join equivale all'esecuzione automatica del comando join, che continuerà a riprovare in caso di fallimento. Il tempo di retry predefinito è 30s:

sh
$ consul join 192.168.48.138

Dopo il completamento del join, ogni nodo è a conoscenza dell'esistenza degli altri. Poiché vm00 è stato specificato in modalità bootstrap, è il leader predefinito. Se non è specificata la modalità bootstrap, il nodo specificato durante il join da tutti i nodi è il leader predefinito. Prima che il leader venga eletto, il cluster non può funzionare correttamente, l'accesso all'interfaccia Web restituirà 500 e alcuni comandi non funzioneranno correttamente. Se un nodo nel cluster è configurato in modalità bootstrap, nessun altro nodo nel cluster dovrebbe essere configurato in modalità bootstrap. Allo stesso tempo, nessun altro nodo dovrebbe utilizzare il parametro bootstrap-expect. Se utilizzato, verrà automaticamente disabilitato.

A questo punto, sul nodo leader (in realtà è possibile verificare su qualsiasi nodo), eseguire il seguente comando per visualizzare le informazioni sui membri del datacenter:

sh
$ consul members
Node      Address              Status  Type    Build   Protocol  DC   Partition  Segment
agent01   192.168.48.138:8301  alive   server  1.16.1  2         dc1  default    <all>
agent02   192.168.48.139:8301  alive   server  1.16.1  2         dc1  default    <all>
agent03   192.168.48.140:8301  alive   server  1.16.1  2         dc1  default    <all>
client01  192.168.48.141:8301  alive   client  1.16.1  2         dc1  default    <default>
  • Node: nome del nodo
  • Address: indirizzo di comunicazione
  • Status: alive indica attivo, left indica offline
  • Type: tipo di agente, due modalità: server e client
  • Build: versione di Consul utilizzata dal nodo. Consul può funzionare con nodi di versioni diverse entro un certo range
  • Protocol: si riferisce alla versione del protocollo Raft utilizzata. Questo protocollo dovrebbe essere coerente su tutti i nodi
  • DC: Data Center. Tutti i nodi nell'output appartengono al datacenter dc1
  • Partition: partizione a cui appartiene il nodo, funzionalità Enterprise. Ogni nodo può comunicare solo con nodi nella stessa partizione
  • Segment: segmento di rete a cui appartiene il nodo, funzionalità Enterprise

Allo stesso modo, se si desidera che un nodo esca, è necessario utilizzare consul leave per consentire al nodo di uscire correttamente e notificare agli altri nodi che sta per uscire. Nel caso di più nodi, l'uscita corretta di un nodo è particolarmente importante poiché riguarda la coerenza dei dati.

TIP

Durante la dimostrazione, tutti i firewall delle macchine virtuali sono stati disattivati. Nell'ambiente di produzione reale, per motivi di sicurezza, dovrebbero essere abilitati. Pertanto, è necessario prestare attenzione a tutte le porte utilizzate da Consul: Required Ports | Consul | HashiCorp Developer.

Successivamente, testare brevemente la coerenza dei dati. Aggiungere i seguenti dati sulla macchina virtuale vm00:

sh
$ consul kv put sys_confg {"name":"consul"}
Success! Data written to: sys_confg

Dopo il salvataggio, accedere agli altri nodi tramite HTTP API per verificare che i dati esistano anche lì (il valore è codificato in base64):

sh
$ curl http://192.168.48.138:8500/v1/kv/sys_confg
[{"LockIndex":0,"Key":"sys_confg","Flags":0,"Value":"ewogICJuYW1lIjoiY29uc3VsIgp9","CreateIndex":2518,"ModifyIndex":2518}]
$ curl http://192.168.48.139:8500/v1/kv/sys_confg
[{"LockIndex":0,"Key":"sys_confg","Flags":0,"Value":"ewogICJuYW1lIjoiY29uc3VsIgp9","CreateIndex":2518,"ModifyIndex":2518}]
$ curl http://192.168.48.140:8500/v1/kv/sys_confg
[{"LockIndex":0,"Key":"sys_confg","Flags":0,"Value":"ewogICJuYW1lIjoiY29uc3VsIgp9","CreateIndex":2518,"ModifyIndex":2518}]

In effetti, le funzionalità di scoperta e registrazione dei servizi fornite da Consul vengono trasmesse agli altri nodi tramite il protocollo gossip. Quando qualsiasi nodo si unisce al datacenter corrente, tutti i nodi percepiscono questo cambiamento.

Esempio di Configurazione Multi-Datacenter

Preparare cinque macchine virtuali. vm00-vm02 sono il cluster dell'esempio precedente e appartengono al datacenter dc1, non verranno modificati. vm03-vm04 appartengono al datacenter dc2. Il datacenter è dc1 per impostazione predefinita all'avvio dell'agente.

TIP

Qui, per la dimostrazione, vengono configurati solo i server, omettendo i client.

Avviare prima vm03 come leader predefinito:

sh
$ consul agent -server -datacenter=dc2 -bind=192.168.48.141 -client=0.0.0.0 -data-dir=/tmp/consul/ -node=agent04 -ui -bootstrap

Avviare vm04 e farlo unire automaticamente al nodo vm03:

sh
$ consul agent -server -datacenter=dc2 -bind=192.168.48.142 -client=0.0.0.0 -data-dir=/tmp/consul/ -node=agent05 -ui -retry-join=192.168.48.141

A questo punto, verificare i membri su vm00 e vm03 rispettivamente:

sh
# vm00-vm02
$ consul members
Node      Address              Status  Type    Build   Protocol  DC   Partition  Segment
agent01   192.168.48.138:8301  alive   server  1.16.1  2         dc1  default    <all>
agent02   192.168.48.139:8301  alive   server  1.16.1  2         dc1  default    <all>
agent03   192.168.48.140:8301  alive   server  1.16.1  2         dc1  default    <all>

# vm03-vm04
$ consul members
Node     Address              Status  Type    Build   Protocol  DC   Partition  Segment
agent04  192.168.48.141:8301  alive   server  1.16.1  2         dc2  default    <all>
agent05  192.168.48.142:8301  alive   server  1.16.1  2         dc2  default    <all>

È possibile vedere che il campo DC è diverso. Poiché questa è una dimostrazione con macchine virtuali, sono tutte nella stessa subnet. Nella realtà, due datacenter potrebbero essere cluster di server in luoghi diversi. Successivamente, fare in modo che un nodo qualsiasi di dc1 si unisca a un nodo qualsiasi di dc2. Qui vm01 si unisce a vm03:

sh
$ consul join -wan 192.168.48.141
Successfully joined cluster by contacting 1 nodes.

Dopo il join riuscito, eseguire il comando per visualizzare i membri WAN:

sh
$ consul members -wan
Node         Address              Status  Type    Build   Protocol  DC   Partition  Segment
agent01.dc1  192.168.48.138:8302  alive   server  1.16.1  2         dc1  default    <all>
agent02.dc1  192.168.48.139:8302  alive   server  1.16.1  2         dc1  default    <all>
agent03.dc1  192.168.48.140:8302  alive   server  1.16.1  2         dc1  default    <all>
agent04.dc2  192.168.48.141:8302  alive   server  1.16.1  2         dc2  default    <all>
agent05.dc2  192.168.48.142:8302  alive   server  1.16.1  2         dc2  default    <all>

$ consul catalog datacenters
dc2
dc1

Finché un nodo qualsiasi di dc1 si unisce a un nodo qualsiasi di dc2, tutti i nodi di entrambi i datacenter percepiscono questo cambiamento. Quando si visualizzano i membri, è possibile vedere i nodi di entrambi i datacenter.

Successivamente, provare ad aggiungere un dato KV sul nodo vm00:

sh
$ consul kv put name consul
Success! Data written to: name

Provare a leggere i dati sul nodo vm01. È possibile vedere che i dati all'interno dello stesso datacenter sono sincronizzati:

sh
$ consul kv get name
consul

Poi provare a leggere i dati su vm03 in un datacenter diverso. Si scopre che i dati tra datacenter diversi non sono sincronizzati:

sh
$ consul kv get name
Error! No key exists at: name

Se si desidera la sincronizzazione dei dati tra più datacenter, è possibile consultare hashicorp/consul-replicate: Consul cross-DC KV replication daemon.

Registrazione e Scoperta dei Servizi

Esistono due modi per registrare i servizi in Consul: registrazione tramite file di configurazione e registrazione tramite API. Per comodità di test, viene preparato in anticipo un servizio Hello World (un esempio dall'articolo gRPC), distribuito in due copie in posizioni diverse. Per la registrazione tramite file di configurazione, consultare Register external services with Consul service discovery | Consul | HashiCorp Developer. Qui viene introdotta solo la registrazione tramite HTTP API.

TIP

Per i servizi locali (insieme al client Consul), è possibile utilizzare direttamente la registrazione del servizio agent. Altrimenti, è necessario utilizzare la registrazione del catalogo.

Consul fornisce SDK per le API HTTP. Per gli SDK di altri linguaggi, consultare Libraries and SDKs - HTTP API | Consul | HashiCorp Developer. Qui viene scaricata la dipendenza per Go:

sh
go get github.com/hashicorp/consul/api

Registrare attivamente il servizio con Consul all'avvio del servizio e deregistrare il servizio da Consul alla chiusura. Di seguito è riportato un esempio:

go
package main

import (
  consulapi "github.com/hashicorp/consul/api"
  "google.golang.org/grpc"
  "google.golang.org/grpc/credentials/insecure"
  pb "grpc_learn/helloworld/hello"
  "log"
  "net"
)

var (
  server01 = &consulapi.AgentService{
        // Deve essere unico
    ID:      "hello-service1",
    Service: "hello-service",
        // Distribuito in due copie, una con porta 8080, l'altra con porta 8081
    Port:    8080,
  }
)

// Registra il servizio
func Register() {
  client, _ := consulapi.NewClient(&consulapi.Config{Address: "192.168.48.138:8500"})
  _, _ = client.Catalog().Register(&consulapi.CatalogRegistration{
    Node:    "hello-server",
    Address: "192.168.2.10",
    Service: server01,
  }, nil)
}

// Deregistra il servizio
func DeRegister() {
  client, _ := consulapi.NewClient(&consulapi.Config{Address: "192.168.48.138:8500"})
  _, _ = client.Catalog().Deregister(&consulapi.CatalogDeregistration{
    Node:      "hello-server",
    Address:   "192.168.2.10",
    ServiceID: server01.ID,
  }, nil)
}

func main() {
  Register()
  defer DeRegister()

  // Ascolta la porta
  listen, err := net.Listen("tcp", ":8080")
  if err != nil {
    panic(err)
  }
  // Crea il server gRPC
  server := grpc.NewServer(
    grpc.Creds(insecure.NewCredentials()),
  )
  // Registra il servizio
  pb.RegisterSayHelloServer(server, &HelloRpc{})
  log.Println("server running...")
  // Esegui
  err = server.Serve(listen)
  if err != nil {
    panic(err)
  }
}

Il codice client utilizza un risolutore personalizzato di Consul per interrogare il registro dei servizi e risolvere gli indirizzi reali.

go
package myresolver

import (
    "fmt"
    consulapi "github.com/hashicorp/consul/api"
    "google.golang.org/grpc/resolver"
)

func NewConsulResolverBuilder(address string) ConsulResolverBuilder {
    return ConsulResolverBuilder{consulAddress: address}
}

type ConsulResolverBuilder struct {
    consulAddress string
}

func (c ConsulResolverBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
    consulResolver, err := newConsulResolver(c.consulAddress, target, cc)
    if err != nil {
       return nil, err
    }
    consulResolver.resolve()
    return consulResolver, nil
}

func (c ConsulResolverBuilder) Scheme() string {
    return "consul"
}

func newConsulResolver(address string, target resolver.Target, cc resolver.ClientConn) (ConsulResolver, error) {
    var reso ConsulResolver
    client, err := consulapi.NewClient(&consulapi.Config{Address: address})
    if err != nil {
       return reso, err
    }
    return ConsulResolver{
       target: target,
       cc:     cc,
       client: client,
    }, nil
}

type ConsulResolver struct {
    target resolver.Target
    cc     resolver.ClientConn
    client *consulapi.Client
}

func (c ConsulResolver) resolve() {
    service := c.target.URL.Opaque
    services, _, err := c.client.Catalog().Service(service, "", nil)
    if err != nil {
       c.cc.ReportError(err)
       return
    }
    var adds []resolver.Address
    for _, catalogService := range services {
       adds = append(adds, resolver.Address{Addr: fmt.Sprintf(fmt.Sprintf("%s:%d", catalogService.Address, catalogService.ServicePort))})
    }

    c.cc.UpdateState(resolver.State{
       Addresses: adds,
       // Strategia di round-robin
       ServiceConfig: c.cc.ParseServiceConfig(
          `{"loadBalancingPolicy":"round_robin"}`),
    })
}

func (c ConsulResolver) ResolveNow(options resolver.ResolveNowOptions) {
    c.resolve()
}

func (c ConsulResolver) Close() {

}

Il client registra il risolutore all'avvio:

go
package main

import (
    "context"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    "google.golang.org/grpc/resolver"
    "grpc_learn/helloworld/client/myresolver"
    hello2 "grpc_learn/helloworld/hello"
    "log"
    "time"
)

func init() {
    // Registra il builder
    resolver.Register(
       // Registra il risolutore Consul personalizzato
       myresolver.NewConsulResolverBuilder("192.168.48.138:8500"),
    )
}

func main() {

    // Stabilisce la connessione, senza verifica crittografica
    conn, err := grpc.Dial("consul:hello-service",
       grpc.WithTransportCredentials(insecure.NewCredentials()),
    )
    if err != nil {
       panic(err)
    }
    defer conn.Close()
    // Crea il client
    client := hello2.NewSayHelloClient(conn)
    for range time.Tick(time.Second) {
       // Chiamata remota
       helloRep, err := client.Hello(context.Background(), &hello2.HelloReq{Name: "client"})
       if err != nil {
          panic(err)
       }
       log.Printf("received grpc resp: %+v", helloRep.String())
    }

}

Avviare prima il server, poi il client. Ci sono due server che forniscono lo stesso servizio ma con indirizzi diversi. La strategia di bilanciamento del carico del client è round-robin, come si può vedere dall'intervallo di tempo nei log del server che la strategia è efficace.

2023/08/29 17:39:54 server running...
2023/08/29 21:03:46 received grpc req: name:"client"
2023/08/29 21:03:48 received grpc req: name:"client"
2023/08/29 21:03:50 received grpc req: name:"client"
2023/08/29 21:03:52 received grpc req: name:"client"
2023/08/29 21:03:54 received grpc req: name:"client"
2023/08/29 21:03:56 received grpc req: name:"client"
2023/08/29 21:03:58 received grpc req: name:"client"
2023/08/29 21:04:00 received grpc req: name:"client"

Questo è un semplice caso d'uso di Consul combinato con gRPC per implementare la registrazione e la scoperta dei servizi.

Golang by www.golangdev.cn edit