Maison  >  Article  >  développement back-end  >  Comment créer un cluster dans Golang

Comment créer un cluster dans Golang

PHPz
PHPzoriginal
2023-04-25 10:42:31578parcourir

1. Introduction

Avec le développement d'Internet, les performances de concurrence des applications sont devenues un sujet de préoccupation croissante. En tant que langage de programmation hautement concurrent, Golang devient de plus en plus populaire parmi les développeurs. Il est livré avec le mécanisme GC, la coroutine et la prise en charge des canaux, ce qui réduit considérablement la complexité et la difficulté de développement du programme.

Cet article expliquera comment utiliser Golang pour créer un cluster simple afin de mieux allouer les requêtes simultanées et d'améliorer les performances et la fiabilité du programme.

2. Le principe de construction d'un cluster

Avant de présenter les opérations spécifiques, comprenons d'abord les principes de construction d'un cluster. De manière générale, un cluster peut être simplement compris comme plusieurs serveurs exécutant la même application ou des applications différentes. Plusieurs serveurs communiquent via le réseau pour remplir des fonctions telles que l'équilibrage de charge et le partage de données.

Dans Golang, il existe un package appelé net/http, qui peut facilement créer un serveur http. En plus du serveur http, nous devons également prendre en charge la découverte des services du serveur, l'équilibrage de charge et d'autres fonctions du cluster. Pour le moment, vous pouvez utiliser des composants tiers comme zookeeper pour l'implémenter.

Dans cet article, nous utiliserons etcd comme centre d'enregistrement de services dans le cluster pour compléter les fonctions d'équilibrage de charge et de découverte de services.

3. Préparation de l'environnement

Avant de commencer la configuration, nous devons installer les outils et l'environnement correspondants.

  1. Environnement golang

Téléchargez et configurez l'environnement golang sur le site officiel Vous pouvez télécharger le package d'installation correspondant depuis "https://golang.org/dl/".

  1. etcd

etcd est un système de stockage clé-valeur distribué open source par la société Coreos, qui peut facilement implémenter des fonctions telles que l'équilibrage de charge et l'enregistrement de services. La version correspondante peut être téléchargée depuis « https://github.com/etcd-io/etcd/releases ».

4. Opérations spécifiques

  1. Écrire un programme de service http

Tout d'abord, nous devons écrire un programme de service http pour gérer les demandes des clients. Ici, nous pouvons utiliser le package net/http intégré au système golang. L'opération la plus basique est la fonction ListenAndServe, qui est utilisée pour démarrer le service http.

Ensuite, nous écrivons un programme pour écouter une requête http locale et renvoyer une phrase au client.

Le code est le suivant :

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprint(w, "Hello World")
    })

    http.ListenAndServe(":8080", nil)
}
  1. Configuration d'etcd

Dans etcd, nous devons d'abord créer une paire clé-valeur pour enregistrer le service. Dans cet exemple, nous utilisons /services/httpServer comme chemin de service et l'adresse IP localhost et le numéro de port 8080 comme valeur de nœud.

Exécutez la commande suivante sous le client etcd pour terminer l'enregistrement :

curl -L http://127.0.0.1:2379/v2/keys/services/httpServer -XPUT -d value='{"host":"localhost", "port":"8080"}'

Configurez plusieurs nœuds de service dans etcd pour obtenir un équilibrage de charge et une haute disponibilité.

  1. Écrire le module d'accès sécurisé etcd

Dans le cluster etcd, nous devons parvenir à un accès aux services et à un équilibrage de charge plus sécurisés. Ici, nous utiliserons le package etcd_sdk, qui peut être facilement utilisé pour se connecter au centre d'enregistrement etcd et lire les nœuds de service.

Il est recommandé lors de l'écriture d'un programme de service de lire les informations d'enregistrement etcd et de surveiller en permanence les modifications d'enregistrement pour maintenir la synchronisation avec le centre d'enregistrement du cluster.

Le code est le suivant :

package main

import (
    "context"
    "fmt"
    "github.com/coreos/etcd/clientv3"
    "net/http"
    "strings"
    "sync"
    "time"
)

var (
    endpoints []string
    currentConfig clientv3.Config
    etcdConfigLocker sync.Mutex
)

func getConfig()(clientv3.Config, error) {
    etcdConfigLocker.Lock()
    defer etcdConfigLocker.Unlock()

    if endpoints == nil {
        return clientv3.Config{}, fmt.Errorf("no endpoints available")
    }

    return clientv3.Config{
        Endpoints: endpoints,
        DialTimeout: 5 * time.Second,
    }, nil
}

type ServiceInfo struct {
    Key    string `json:"key"`
    Value  string `json:"value"`
}

func main() {
    endpoints = append(endpoints, "127.0.0.1:2379")
    readServices()

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        url := fmt.Sprintf("http://%s%s", getService(), r.URL.Path)
        fmt.Printf("Forward %s => %s\n", r.URL.Path, url)
        http.Redirect(w, r, url, 307)
    })
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        panic(err)
    }
    readServices()
}

func getService() string {
    config, err := getConfig()
    if err != nil {
        panic(err)
    }

    client, err := clientv3.New(config)
    if err != nil {
        panic(err)
    }

    defer client.Close()

    prefix := "services/httpServer"

    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    resp, err := client.Get(ctx, prefix, clientv3.WithPrefix())
    cancel()
    if err != nil {
        panic(err)
    }

    services := make([]*ServiceInfo, 0)
    for _, kv := range resp.Kvs {
        services = append(services, &ServiceInfo{
            Key: string(kv.Key),
            Value: string(kv.Value),
        })
    }

    if len(services) == 0 {
        panic(fmt.Errorf("no endpoint available"))
    }

    return strings.Replace(services[0].Value, "\"", "", -1)
}

func readServices() {
    go func() {
        for {
            getConfigFromEtcd()
            time.Sleep(5 * time.Second)
        }
    }()
}

func getConfigFromEtcd() {
    client, err := clientv3.New(currentConfig)
    if err != nil {
        fmt.Printf("ERROR: create etcd client failed: %s\n", err.Error())
        return
    }

    defer client.Close()

    key := "services/httpServer"
    ctx, cancel := context.WithTimeout(context.Background(), 10 * time.Second)
    resp, err := client.Get(ctx, key, clientv3.WithPrefix())
    cancel()

    if err != nil {
        fmt.Printf("ERROR: get etcd key(%s) failed: %s\n", key, err.Error())
        return
    }

    tempEndpoints := make([]string, 0, len(resp.Kvs))
    for _, itm := range resp.Kvs {
        value := string(itm.Value)
        tempEndpoints = append(tempEndpoints, value)
    }

    fmt.Printf("INFO: get endpoints from etcd(%s) success: %v\n", currentConfig.Endpoints, tempEndpoints)

    currentConfig = clientv3.Config{
        Endpoints: tempEndpoints,
        DialTimeout: 5 * time.Second,
    }
}

Dans le code, nous utilisons le package clientv3 dans le SDK etcd pour nous connecter au centre d'enregistrement etcd et en obtenir des informations sur le nœud de service. Les fonctions getConfig() et getConfigFromEtcd() sont utilisées pour lire les informations du registre etcd.

  1. Exécuter le programme de service

Après avoir configuré les étapes ci-dessus, nous pouvons exécuter le programme. Ouvrez le terminal, basculez vers le répertoire du projet et exécutez la commande suivante :

go run main.go

Après une opération réussie, ouvrez le navigateur et visitez http://127.0.0.1:8080. Vous verrez que le programme imprime "Hello World", indiquant que le programme a été exécuté avec succès.

Dans cet exemple, nous utilisons le service http. Dans les projets réels, nous pouvons également utiliser des protocoles hautes performances comme grpc pour améliorer les performances du programme.

5. Résumé

Dans cet article, nous avons présenté les principes et les opérations spécifiques de l'utilisation de Golang pour construire un cluster. En utilisant le centre d'enregistrement etcd et le package SDK correspondant, nous réalisons l'enregistrement, la lecture et la maintenance dynamique des nœuds de service. Cela contribue à améliorer les performances et la fiabilité du programme et conduit à une meilleure expérience utilisateur.

Dans les applications pratiques, vous devez également faire attention à la sécurité et à la tolérance aux pannes du programme pour garantir la fiabilité du programme.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn