package main
import (
"context"
"fmt"
"go.etcd.io/etcd/clientv3"
"log"
"time"
)
func main() {
cli, err := clientv3.New(clientv3.Config{
Endpoints: []string{"localhost:2379", "localhost:2479", "localhost:2579"},
DialTimeout: 5 * time.Second,
})
if err != nil {
log.Fatal(err)
}
kv := clientv3.NewKV(cli)
putResp, err := kv.Put(context.TODO(),"/test/key1", "Hello etcd!")
fmt.Printf("PutResponse: %v, err: %v\n", putResp, err)
}
本机有三个 etcd 节点,分别为 2379,2479,2579。是以集群方式搭建的,在测试g olang 链接 etcd 集群时,有以下疑问:
1、杀死其中两个节点,只有有一个节点存活,go 代码就能跑通,它的实现原理是什么,原谅我找源码找了半天没找到。想问下他的运行机制是怎样的?
2、golang 链接 etcd 集群的方式就是这样吗?就是链接多个,只要有一个存活就不影响程序运行,这是 etcd 集群正确的使用方式吗?
感谢大佬,好人一生平安。
1
gy0624ww 2019-11-27 17:48:19 +08:00
一个节点当然能跑通了,etcd 是分布式存储,你一个节点就是单机模式了呗
etcd 多个节点会有选举,选出个 leader 和客户端交互。 你说的就一个存活了,那肯定那个存活的就是 leader 了。 |
2
xkeyideal 2019-11-27 17:53:47 +08:00
给你简单解释一下:
1. etcd 的通信是基于 grpc 的,grpc 每次非 stream 的请求,每次使用的 server 地址都可能不一样,详细看可以看 clientv3 的 balance 源码,看看 etcd 怎么做 grpc 连接的负载均衡的,记着是每次请求 2. etcd 是基于 raft 协议的,写请求会自动转到主,读请求(不包括非线性读)可以读从,线性读的机制比较复杂,你可以认为是主节点响应的(这里比较复杂,建议看源码) 3. raft 集群,如果主挂掉,那么其他机器会自动选主,所以你说的一台机器挂掉是不影响 etcd 的使用的,当挂掉的机器恢复后,会变成从机,然后从主机同步数据 4. etcd golang clientv3 连接 etcd servers 的代码相对来说比较简单,很容易看懂,但想要完整的理解全套逻辑,需要看 server 的部分代码,raft 部分基本上不需要看,只需要理解 raft 协议本身即可 |
3
xkeyideal 2019-11-27 17:57:38 +08:00
5. clientv3 里面有定时从 etcd 集群更新当前 etcd 集群可提供服务机器的代码 https://github.com/etcd-io/etcd/blob/master/clientv3/client.go#L193, 所以并不是你说的只要有一个存活就不影响程序运行,那么说明你的测试密度不够,客户端肯定不是实时响应服务端机器变化的
|
4
jejer 2019-11-28 09:29:56 +08:00
client 同时尝试 3 个 endpoint
|