Etcd - 分佈式配置中心

Etcd 簡介

Etcd 是一種分佈式 kv 存儲設施, 他具有一定的一致性,高性能,高可用的方案. 類似的 zookeeper, 但沒有 zookeeper 那麼重型,功能也沒有覆蓋那麼多. 簡單直接的應用就是配置中心

架構設計總覽

clients 爲多個需要 配置的服務, 中間層爲 多個 grpc-proxy 做均衡負載, 以免一個 proxy 掛了之後 導致單點問題. grpc-proxy 可以 同時訪問多個 etcd 服務器,進行 kv 的操作. 如果某一個 server 掛了,會自動訪問別的 集羣中的其他 server 以保證高可用.

etcd cluster 至少爲 3 臺, 如果小於 3 臺則無法進行選舉,造成集羣 不可用. (這裏需要用 promethus 進行監控預警)

etcd cluster 本地搭建

  1. 本地安裝 etcd,或者直接下載預編譯好的執行文件
    https://github.com/etcd-io/etcd/releases
  2. 獲取 etcd 源碼 (其實只是要一個配置文件 Procfile)
  3. 安裝 goreman -> go get github.com/mattn/goreman
  4. 修改源碼根目錄的 Procfile
# Use goreman to run `go get github.com/mattn/goreman`
etcd1: /Users/vincent/Downloads/etcd-v3.3.9-darwin-amd64/etcd --name infra1 --listen-client-urls http://127.0.0.1:2379 --advertise-client-urls http://127.0.0.1:2379 --listen-peer-urls http://127.0.0.1:12380 --initial-advertise-peer-urls http://127.0.0.1:12380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380,infra4=http://127.0.0.1:42380,infra5=http://127.0.0.1:52380' --initial-cluster-state new --enable-pprof --log-output=stderr
etcd2: /Users/vincent/Downloads/etcd-v3.3.9-darwin-amd64/etcd --name infra2 --listen-client-urls http://127.0.0.1:22379 --advertise-client-urls http://127.0.0.1:22379 --listen-peer-urls http://127.0.0.1:22380 --initial-advertise-peer-urls http://127.0.0.1:22380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380,infra4=http://127.0.0.1:42380,infra5=http://127.0.0.1:52380' --initial-cluster-state new --enable-pprof --log-output=stderr
etcd3: /Users/vincent/Downloads/etcd-v3.3.9-darwin-amd64/etcd --name infra3 --listen-client-urls http://127.0.0.1:32379 --advertise-client-urls http://127.0.0.1:32379 --listen-peer-urls http://127.0.0.1:32380 --initial-advertise-peer-urls http://127.0.0.1:32380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380,infra4=http://127.0.0.1:42380,infra5=http://127.0.0.1:52380' --initial-cluster-state new --enable-pprof --log-output=stderr
etcd4: /Users/vincent/Downloads/etcd-v3.3.9-darwin-amd64/etcd --name infra4 --listen-client-urls http://127.0.0.1:42379 --advertise-client-urls http://127.0.0.1:42379 --listen-peer-urls http://127.0.0.1:42380 --initial-advertise-peer-urls http://127.0.0.1:42380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380,infra4=http://127.0.0.1:42380,infra5=http://127.0.0.1:52380' --initial-cluster-state new --enable-pprof --log-output=stderr
etcd5: /Users/vincent/Downloads/etcd-v3.3.9-darwin-amd64/etcd --name infra5 --listen-client-urls http://127.0.0.1:52379 --advertise-client-urls http://127.0.0.1:52379 --listen-peer-urls http://127.0.0.1:52380 --initial-advertise-peer-urls http://127.0.0.1:52380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380,infra4=http://127.0.0.1:42380,infra5=http://127.0.0.1:52380' --initial-cluster-state new --enable-pprof --log-output=stderr
proxy1: /Users/vincent/Downloads/etcd-v3.3.9-darwin-amd64/etcd grpc-proxy start --endpoints=127.0.0.1:2379,127.0.0.1:22379,127.0.0.1:32379,127.0.0.1:42379,127.0.0.1:52379 --listen-addr=127.0.0.1:23790 --advertise-client-url=127.0.0.1:23790 --enable-pprof
proxy2: /Users/vincent/Downloads/etcd-v3.3.9-darwin-amd64/etcd grpc-proxy start --endpoints=127.0.0.1:2379,127.0.0.1:22379,127.0.0.1:32379,127.0.0.1:42379,127.0.0.1:52379 --listen-addr=127.0.0.1:23791 --advertise-client-url=127.0.0.1:23791 --enable-pprof
  1. 啓動集羣 goreman -f Procfile start

配置解讀

配置了 5 個 etcd 服務模擬不同的 server, 配置了 2 個 proxy, 模擬兩個 grpc-proxy 當做均衡負載
–listen-client-urls etcd 監聽的地址
–listen-peer-urls 集羣內部 member 互相監聽的地址
–name 集羣成員的名字
–advertise-client-urls 集羣內成員對外發布信息的地址
–initial-advertise-peer-urls 對集羣內發佈信息的地址
–initial-cluster-state Set to new for all members present during initial static or DNS bootstrapping. If this option is set to existing, etcd will attempt to join the existing cluster. If the wrong value is set, etcd will attempt to start but fail safely.
–initial-cluster-token 集羣的標示

5 個 etcd server 形成 etcd-cluster-1, 2 個 proxy 對這個集羣進行代理

集羣檢查

ETCDCTL_API=3 ./etcdctl endpoint –endpoints=127.0.0.1:2379,127.0.0.1:22379,127.0.0.1:32379,127.0.0.1:42379,127.0.0.1:52379 status -w table

λ ETCDCTL_API=3 ./etcdctl endpoint --endpoints=127.0.0.1:2379,127.0.0.1:22379,127.0.0.1:32379,127.0.0.1:42379,127.0.0.1:52379 status -w table
+-----------------+------------------+---------+---------+-----------+-----------+------------+
|    ENDPOINT     |        ID        | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+-----------------+------------------+---------+---------+-----------+-----------+------------+
|  127.0.0.1:2379 | 8211f1d0f64f3269 |   3.3.9 |   25 kB |     false |         2 |         12 |
| 127.0.0.1:22379 | 91bc3c398fb3c146 |   3.3.9 |   25 kB |     false |         2 |         12 |
| 127.0.0.1:32379 | fd422379fda50e48 |   3.3.9 |   25 kB |     false |         2 |         12 |
| 127.0.0.1:42379 | 45d559f8148de837 |   3.3.9 |   25 kB |     false |         2 |         12 |
| 127.0.0.1:52379 | c91263fe1e1dd3b5 |   3.3.9 |   25 kB |      true |         2 |         12 |
+-----------------+------------------+---------+---------+-----------+-----------+------------+
λ ./etcdctl cluster-health
member 45d559f8148de837 is healthy: got healthy result from http://127.0.0.1:42379
member 8211f1d0f64f3269 is healthy: got healthy result from http://127.0.0.1:2379
member 91bc3c398fb3c146 is healthy: got healthy result from http://127.0.0.1:22379
member c91263fe1e1dd3b5 is healthy: got healthy result from http://127.0.0.1:52379
member fd422379fda50e48 is healthy: got healthy result from http://127.0.0.1:32379
cluster is healthy

編寫測試客戶端進行 kv 操作

go get go.etcd.io/etcd

package main

import (
	"context"
	"fmt"
	"log"
	"strconv"
	"time"

	"go.etcd.io/etcd/clientv3"
	"vincent.com/etcd/etcd/etcdserver/api/v3rpc/rpctypes"
)

func main() {

	cli, err := clientv3.New(clientv3.Config{
		Endpoints:   []string{"http://127.0.0.1:23790", "http://127.0.0.1:23791"},
		DialTimeout: 5 * time.Second,
	})
	if err != nil {
		// handle error!
		log.Fatalln(err.Error())
	}
	defer cli.Close()
	defer cli.Delete(context.Background(), "sample_key")

	for index := 0; index < 10000; index++ {
		insertKV(cli, "sample_key", "sample_value"+strconv.Itoa(index))
		if err != nil {
			break
		}
	}
	resp, err := cli.Get(context.Background(), "sample_key")
	if err != nil {
		log.Fatalln("get key error", err)
	}
	fmt.Printf("get the sample_key: %v\n", resp.Kvs)
}

func insertKV(cli *clientv3.Client, key string, value string) (err error) {
	time.Sleep(2 * time.Millisecond)
	_, err = cli.Put(context.Background(), key, value)
	// cancel()
	if err != nil {
		switch err {
		case context.Canceled:
			log.Fatalf("ctx is canceled by another routine: %v", err)

		case context.DeadlineExceeded:
			log.Fatalf("ctx is attached with a deadline is exceeded: %v", err)
		case rpctypes.ErrEmptyKey:
			log.Fatalf("client-side error: %v", err)
		default:
			log.Fatalf("bad cluster endpoints, which are not etcd servers: %v", err)
		}
	}
	return
}

客戶端解讀

etcd 客戶端支持集羣, 所以直接可以連接兩個 proxy
這裏進行了 1w 此的寫入,每次寫入會有 x ms 的延遲(我怕我的 mbp 受不了)

客戶端測試

  • 運行客戶端程序
  • 模擬 etcd server 掛掉 goreman run stop etcd2
  • 當集羣內健康機器少於 3 臺的時候,客戶端報錯,集羣整體不可用

集羣性能檢測

λ ETCDCTL_API=3 ./etcdctl check perf load="l" --endpoints=127.0.0.1:2379,127.0.0.1:22379,127.0.0.1:32379,127.0.0.1:42379,127.0.0.1:52379
 60 / 60 Booooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo! 100.00%1m0s
PASS: Throughput is 150 writes/s
PASS: Slowest request took 0.388842s
PASS: Stddev is 0.029037s
PASS

注意:

如果用命令行,記得加 ETCDCTL_API=3

#Golang #Etcd

 golang-uuidv1

 

Etcd - 分佈式配置中心2 - runtime切換配置 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章