Rumah >pembangunan bahagian belakang >Golang >Cara membina gugusan di golang

Cara membina gugusan di golang

PHPz
PHPzasal
2023-04-25 10:42:31595semak imbas

1. Kata Pendahuluan

Dengan perkembangan Internet, prestasi bersamaan aplikasi telah menjadi topik yang semakin membimbangkan. Sebagai bahasa pengaturcaraan yang sangat serentak, golang menjadi semakin popular di kalangan pembangun. Ia datang dengan mekanisme GC, coroutine dan sokongan saluran, yang sangat mengurangkan kerumitan dan kesukaran pembangunan program.

Artikel ini akan memperkenalkan cara menggunakan golang untuk membina gugusan mudah untuk memperuntukkan permintaan serentak dengan lebih baik dan meningkatkan prestasi serta kebolehpercayaan program.

2. Prinsip membina kluster

Sebelum memperkenalkan operasi khusus, mari kita fahami prinsip membina kluster. Secara umumnya, kluster boleh difahami secara ringkas sebagai berbilang pelayan yang menjalankan aplikasi yang sama atau berbeza. Pelbagai pelayan berkomunikasi melalui rangkaian untuk melengkapkan fungsi seperti pengimbangan beban dan perkongsian data.

Di golang, terdapat pakej yang dipanggil net/http, yang boleh membina pelayan http dengan mudah. Selain pelayan http, kami juga perlu menyokong penemuan perkhidmatan pelayan, pengimbangan beban dan fungsi lain dalam kluster. Pada masa ini, anda boleh menggunakan komponen pihak ketiga seperti zookeeper untuk melaksanakannya.

Dalam artikel ini, kami akan menggunakan etcd sebagai pusat pendaftaran perkhidmatan dalam kluster untuk melengkapkan fungsi pengimbangan beban dan penemuan perkhidmatan.

3. Persediaan persekitaran

Sebelum memulakan konfigurasi, kami perlu memasang alatan dan persekitaran yang sepadan.

  1. persekitaran golang

Muat turun dan konfigurasikan persekitaran golang di tapak web rasmi Anda boleh memuat turun pakej pemasangan yang sepadan dari "https://golang.org/dl/. " .

  1. etcd

etcd ialah sistem storan nilai kunci teragih sumber terbuka oleh syarikat coreos, yang boleh merealisasikan fungsi seperti pengimbangan beban dan pendaftaran perkhidmatan dengan mudah. Versi yang sepadan boleh dimuat turun dari "https://github.com/etcd-io/etcd/releases".

4. Operasi khusus

  1. Tulis program perkhidmatan http

Pertama, kita perlu menulis program perkhidmatan http untuk mengendalikan permintaan pelanggan. Di sini kita boleh menggunakan pakej net/http yang terbina dalam sistem golang Operasi yang paling asas ialah fungsi ListenAndServe, yang digunakan untuk memulakan perkhidmatan http.

Seterusnya, kami menulis program untuk mendengar permintaan http tempatan dan mengembalikan ayat kepada klien.

Kod adalah seperti berikut:

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. Mengkonfigurasi etcd

Dalam etcd, kita perlu mencipta pasangan nilai kunci terlebih dahulu untuk mendaftar perkhidmatan tersebut. Dalam contoh ini, kami menggunakan /services/httpServer sebagai laluan perkhidmatan dan alamat IP localhost dan nombor port 8080 sebagai nilai nod.

Laksanakan arahan berikut di bawah klien etcd untuk melengkapkan pendaftaran:

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

Konfigurasikan berbilang nod perkhidmatan dalam etcd untuk mencapai pengimbangan beban dan ketersediaan tinggi.

  1. Tulis modul akses selamat etcd

Dalam kluster etcd, kita perlu mencapai akses perkhidmatan dan pengimbangan beban yang lebih selamat. Di sini kami akan menggunakan pakej etcd_sdk, yang boleh digunakan dengan mudah untuk menyambung ke pusat pendaftaran etcd dan membaca nod perkhidmatan.

Adalah disyorkan bahawa semasa menulis program perkhidmatan, anda harus membaca maklumat pendaftaran dll dan sentiasa memantau perubahan pendaftaran untuk mengekalkan penyegerakan dengan pusat pendaftaran kluster.

Kod adalah seperti berikut:

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,
    }
}

Dalam kod, kami menggunakan pakej clientv3 dalam etcd sdk untuk menyambung ke pusat pendaftaran etcd dan mendapatkan maklumat nod perkhidmatan daripadanya. Fungsi getConfig() dan getConfigFromEtcd() digunakan untuk membaca maklumat pendaftaran etcd.

  1. Jalankan program perkhidmatan

Selepas mengkonfigurasi langkah di atas, kita boleh menjalankan program tersebut. Buka terminal, tukar ke direktori projek, dan laksanakan arahan berikut:

go run main.go

Selepas operasi berjaya, buka penyemak imbas dan lawati http://127.0.0.1:8080 Anda akan melihat cetakan program keluar "Hello" World", menunjukkan bahawa program telah berjalan dengan jayanya.

Dalam contoh ini, kami menggunakan perkhidmatan http Dalam projek sebenar, kami juga boleh menggunakan protokol berprestasi tinggi seperti grpc untuk meningkatkan prestasi program.

5. Ringkasan

Dalam artikel ini, kami memperkenalkan prinsip dan operasi khusus menggunakan golang untuk membina gugusan. Dengan menggunakan pusat pendaftaran etcd dan pakej sdk yang sepadan, kami menyedari pendaftaran, pembacaan dan penyelenggaraan dinamik nod perkhidmatan. Ini membantu meningkatkan prestasi dan kebolehpercayaan program dan membawa kepada pengalaman pengguna yang lebih baik.

Dalam aplikasi praktikal, anda juga perlu memberi perhatian kepada keselamatan dan toleransi kesalahan program untuk memastikan kebolehpercayaan program.

Atas ialah kandungan terperinci Cara membina gugusan di golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn