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.
Muat turun dan konfigurasikan persekitaran golang di tapak web rasmi Anda boleh memuat turun pakej pemasangan yang sepadan dari "https://golang.org/dl/. " .
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
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) }
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.
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.
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!