Maison > Article > développement back-end > Comment créer un cluster dans Golang
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.
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/".
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
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) }
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é.
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.
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!