etcd是什么?
A highly-available key value store for shared configuration and service discovery.是一個鍵值存儲倉庫,用於配置共享和服務發現
概念:高可用的分布式key-value存儲,可以用於配置共享和服務發現。
類似項目:zookeeper和consul
開發語言:Go
接口:提供restful的http接口,使用簡單
實現算法:基於raft算法的強一致性、高可用的服務存儲目錄
- 簡單:基於HTTP+JSON的API讓你用curl命令就可以輕松使用。
- 安全:可選SSL客戶認證機制。
- 快速:每個實例每秒支持一千次寫操作。
- 可信:使用Raft算法充分實現了分布式。
應用場景:
服務發現和服務注冊
配置中心
分布式鎖
master選舉
和ZK類似,ETCD有很多使用場景,包括:
- 配置管理
- 服務注冊於發現
- 選主
- 應用調度
- 分布式隊列
- 分布式鎖
ETCD集群是一個分布式系統,由多個節點相互通信構成整體對外服務,每個節點都存儲了完整的數據,並且通過Raft協議保證每個節點維護的數據是一致的。
服務發現(Service Discovery)
要解決的是分布式系統中最常見的問題之一,即在同一個分布式集群中的進程或服務如何才能找到對方並建立連接。從本質上說,服務發現就是想要了解集群中是否有進程在監聽udp或tcp端口,並且通過名字就可以進行查找和連接。
消息發布與訂閱
在分布式系統中,最為適用的組件間通信方式是消息發布與訂閱機制。具體而言,即構建一個配置共享中心,數據提供者在這個配置中心發布消息,而消息使用者則訂閱他們關心的主題,一旦相關主題有消息發布,就會實時通知訂閱者。通過這種方式可以實現分布式系統配置的集中式管理與實時動態更新。
負載均衡
在分布式系統中,為了保證服務的高可用以及數據的一致性,通常都會把數據和服務部署多份,以此達到對等服務,即使其中的某一個服務失效了,也不影響使用。這樣的實現雖然會導致一定程度上數據寫入性能的下降,但是卻能實現數據訪問時的負載均衡。因為每個對等服務節點上都存有完整的數據,所以用戶的訪問流量就可以分流到不同的機器上。
etcd搭建
a. 下載etcd release版本:https://github.com/coreos/etcd/releases/ b. ./bin/etcd即可以啟動etcd c. 使用etcdctl工具更改配置
https://github.com/coreos/etcd/releases/download/v3.3.0/etcd-v3.3.0-linux-amd64.tar.gz
[root@greg02 etcd3.3]#ls
default.etcd Documentation etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md
[root@greg02 etcd3.3]#etcdctl set test asdf
asdf
[root@greg02 etcd3.3]#etcdctl get test
asdf
etcd的golang操作:
package main import ( "context" "encoding/json" "fmt" "time" "github.com/coreos/etcd/clientv3" ) const ( EtcdKey = "/ningxin/backend/logagent/config/192.168.56.1" ) type LogConf struct { Path string `json:"path"` Topic string `json:"topic"` } func SetLogConfToEtcd() { cli, err := clientv3.New(clientv3.Config{ Endpoints: []string{"localhost:2379", "localhost:22379", "localhost:32379"}, DialTimeout: 5 * time.Second, }) if err != nil { fmt.Println("connect failed, err:", err) return } fmt.Println("connect succ") defer cli.Close() var logConfArr []LogConf logConfArr = append( logConfArr, LogConf{ Path: "D:/project/nginx/logs/access.log", Topic: "nginx_log", }, ) logConfArr = append( logConfArr, LogConf{ Path: "D:/project/nginx/logs/error.log", Topic: "nginx_log_err", }, ) data, err := json.Marshal(logConfArr) if err != nil { fmt.Println("json failed, ", err) return } ctx, cancel := context.WithTimeout(context.Background(), time.Second) _, err = cli.Put(ctx, EtcdKey, string(data)) cancel() if err != nil { fmt.Println("put failed, err:", err) return } ctx, cancel = context.WithTimeout(context.Background(), time.Second) resp, err := cli.Get(ctx, EtcdKey) cancel() if err != nil { fmt.Println("get failed, err:", err) return } for _, ev := range resp.Kvs { fmt.Printf("%s : %s\n", ev.Key, ev.Value) } } func main() { SetLogConfToEtcd() EtcdExmaple() } func EtcdExmaple() { cli, err := clientv3.New(clientv3.Config{ Endpoints: []string{"localhost:2379", "localhost:22379", "localhost:32379"}, DialTimeout: 5 * time.Second, }) if err != nil { fmt.Println("connect failed, err:", err) return } fmt.Println("connect succ") defer cli.Close() ctx, cancel := context.WithTimeout(context.Background(), time.Second) _, err = cli.Put(ctx, "/logagent/conf/", "sample_value") cancel() if err != nil { fmt.Println("put failed, err:", err) return } ctx, cancel = context.WithTimeout(context.Background(), time.Second) resp, err := cli.Get(ctx, "/logagent/conf/") cancel() if err != nil { fmt.Println("get failed, err:", err) return } for _, ev := range resp.Kvs { fmt.Printf("%s : %s\n", ev.Key, ev.Value) } }
用etcd構建的web日志監控:https://github.com/ningxin1718/logweb