Heim >Backend-Entwicklung >Golang >So bauen Sie einen Cluster in Golang auf
1. Einführung
Mit der Entwicklung des Internets ist die Parallelitätsleistung von Anwendungen zu einem Thema von zunehmender Bedeutung geworden. Als hochgradig nebenläufige Programmiersprache erfreut sich Golang bei Entwicklern immer größerer Beliebtheit. Es verfügt über GC-Mechanismus, Coroutine- und Kanalunterstützung, was die Komplexität und Entwicklungsschwierigkeiten des Programms erheblich reduziert.
In diesem Artikel erfahren Sie, wie Sie mit Golang einen einfachen Cluster erstellen, um gleichzeitige Anforderungen besser zuzuordnen und die Leistung und Zuverlässigkeit des Programms zu verbessern.
2. Das Prinzip des Clusteraufbaus
Bevor wir die spezifischen Vorgänge vorstellen, wollen wir zunächst die Prinzipien des Clusteraufbaus verstehen. Im Allgemeinen kann ein Cluster einfach als mehrere Server verstanden werden, auf denen dieselben oder unterschiedliche Anwendungen ausgeführt werden. Mehrere Server kommunizieren über das Netzwerk, um Funktionen wie Lastausgleich und Datenfreigabe auszuführen.
In Golang gibt es ein Paket namens net/http, mit dem sich problemlos ein http-Server erstellen lässt. Zusätzlich zum http-Server müssen wir auch die Serverdiensterkennung, den Lastausgleich und andere Funktionen im Cluster unterstützen. Derzeit können Sie zur Implementierung Komponenten von Drittanbietern wie zookeeper verwenden.
In diesem Artikel verwenden wir etcd als Service-Registrierungscenter im Cluster, um die Funktionen des Lastausgleichs und der Serviceerkennung abzuschließen.
3. Umgebungsvorbereitung
Bevor wir mit der Konfiguration beginnen, müssen wir die entsprechenden Tools und Umgebung installieren.
Laden Sie die Golang-Umgebung auf der offiziellen Website herunter und konfigurieren Sie sie. Sie können das entsprechende Installationspaket von „https://golang.org/dl/“ herunterladen.
etcd ist ein verteiltes Schlüsselwertspeichersystem, das von der Firma Coreos als Open-Source-Lösung bereitgestellt wird und problemlos Funktionen wie Lastausgleich und Dienstregistrierung implementieren kann. Die entsprechende Version kann unter „https://github.com/etcd-io/etcd/releases“ heruntergeladen werden.
4. Spezifische Vorgänge
Zunächst müssen wir ein http-Dienstprogramm schreiben, um Kundenanfragen zu bearbeiten. Hier können wir das in das Golang-System integrierte Net/http-Paket verwenden. Die grundlegendste Operation ist die ListenAndServe-Funktion, die zum Starten des http-Dienstes verwendet wird.
Als nächstes schreiben wir ein Programm, um eine lokale HTTP-Anfrage abzuhören und einen Satz an den Client zurückzugeben.
Der Code lautet wie folgt:
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) }
In etcd müssen wir zunächst ein Schlüssel-Wert-Paar erstellen, um den Dienst zu registrieren. In diesem Beispiel verwenden wir /services/httpServer als Dienstpfad und die Localhost-IP-Adresse und Portnummer 8080 als Knotenwert.
Führen Sie den folgenden Befehl unter dem etcd-Client aus, um die Registrierung abzuschließen:
curl -L http://127.0.0.1:2379/v2/keys/services/httpServer -XPUT -d value='{"host":"localhost", "port":"8080"}'
Konfigurieren Sie mehrere Dienstknoten in etcd, um Lastausgleich und hohe Verfügbarkeit zu erreichen.
Im etcd-Cluster müssen wir einen sichereren Dienstzugriff und Lastausgleich erreichen. Hier verwenden wir das Paket etcd_sdk, mit dem Sie bequem eine Verbindung zum etcd-Registrierungscenter herstellen und Serviceknoten lesen können.
Es wird empfohlen, beim Schreiben von Dienstprogrammen die etcd-Registrierungsinformationen zu lesen und Registrierungsänderungen ständig zu überwachen, um die Synchronisierung mit dem Cluster-Registrierungscenter aufrechtzuerhalten.
Der Code lautet wie folgt:
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, } }
Im Code verwenden wir das clientv3-Paket im etcd sdk, um eine Verbindung zum etcd-Registrierungscenter herzustellen und von dort Dienstknoteninformationen zu erhalten. Die Funktionen getConfig() und getConfigFromEtcd() werden zum Lesen von etcd-Registrierungsinformationen verwendet.
Nachdem wir die obigen Schritte konfiguriert haben, können wir das Programm ausführen. Öffnen Sie das Terminal, wechseln Sie in das Projektverzeichnis und führen Sie den folgenden Befehl aus:
go run main.go
Öffnen Sie nach erfolgreichem Vorgang den Browser und besuchen Sie http://127.0.0.1:8080. Sie werden sehen, dass das Programm „Hello World“ ausgibt. Zeigt an, dass das Programm erfolgreich ausgeführt wurde.
In diesem Beispiel verwenden wir den http-Dienst. In tatsächlichen Projekten können wir auch Hochleistungsprotokolle wie grpc verwenden, um die Programmleistung zu verbessern.
5. Zusammenfassung
In diesem Artikel haben wir die Prinzipien und spezifischen Vorgänge der Verwendung von Golang zum Aufbau eines Clusters vorgestellt. Durch die Verwendung des etcd-Registrierungscenters und des entsprechenden SDK-Pakets realisieren wir die Registrierung, das Lesen und die dynamische Wartung von Serviceknoten. Dies trägt dazu bei, die Leistung und Zuverlässigkeit des Programms zu verbessern und führt zu einer besseren Benutzererfahrung.
In praktischen Anwendungen müssen Sie auch auf die Sicherheit und Fehlertoleranz des Programms achten, um die Zuverlässigkeit des Programms sicherzustellen.
Das obige ist der detaillierte Inhalt vonSo bauen Sie einen Cluster in Golang auf. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!