golang etcd容器构建与客户端操作踩坑实操
1.问题说明
在用 go-zero 实现相关服务时一直报错,从报错信息看应该是 etcd 的容器有问题,应该是之前的构建哪里出错了,所以重新构建 etcd 容器应用。
记录下主要的踩坑情况:
- 1.连接 etcd 容器没有问题,但是写入数据时一直报错,报超时错,可以看下面的操作记录,但本人就构建了一个单节点的 etcd,也用不到 etcd 集群功能
# ./etcdctl --endpoints=0.0.0.0:2379 --write-out=table endpoint health {"level":"warn","ts":"2024-08-01T10:50:35.003109+0800","logger":"client","caller":"v3@v3.5.12/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"etcd-endpoints://0xc0002e2a80/0.0.0.0:2379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = latest balancer error: last connection error: connection error: desc = \"error reading server preface: read tcp 127.0.0.1:49164->127.0.0.1:2379: read: connection reset by peer\""} +--------------+--------+--------------+---------------------------+ | ENDPOINT | HEALTH | TOOK | ERROR | +--------------+--------+--------------+---------------------------+ | 0.0.0.0:2379 | false | 5.007223857s | context deadline exceeded | +--------------+--------+--------------+---------------------------+ Error: unhealthy cluster
- 2.通过 golang 实现 etcd 客户端时,一直报依赖的问题,最后发现 v3.3 问题很多,后面就切 v3.5了,之后依赖问题解决
下面记录下整体的工作流。
2. etcd 容器构建
具体操作参考:
以下是具体的一些操作。
这里的容器用到的镜像是:quay.io/coreos/etcd:v3.5.12
,所以你需要 docker pull 先拉取下来。
接下来是具体的一些容器构建的工作。
# 创建目录,数据与配置目录 mkdir -p /data/containers/etcd/{data,config} # 创建配置文件 vi /data/containers/etcd/config/etcd.conf.yml --- name: etcd-s1 data-dir: /var/etcd listen-client-urls: http://0.0.0.0:2379 advertise-client-urls: http://0.0.0.0:2379 listen-peer-urls: http://0.0.0.0:2380 initial-advertise-peer-urls: http://0.0.0.0:2380 initial-cluster: etcd-s1=http://0.0.0.0:2380 initial-cluster-token: etcd-cluster initial-cluster-state: new logger: zap log-level: info #log-outputs: stderr --- 说明: 特殊参数说明: name: etcd member 名称,可根据实际情况修改 data-dir: etcd 数据目录,可根据实际情况修改 listen-client-urls: client 流量监听地址,没特殊需求按文档填写即可 advertise-client-urls: 该 member 向外部通告的客户端 url 列表,单节点部署时不需要修改,集群部署模式需修改为容器所在节点对外提供服务的 IP listen-peer-urls: peer 流量监听地址,没特殊需求按文档填写即可 initial-advertise-peer-urls: 该 member 向同一集群内其他 member 通告的 peer url 列表,单节点部署时不需要修改,集群部署模式需修改为容器所在节点对外提供服务的 IP initial-cluster: 初始化集群节点信息,单节点部署时不需要修改,集群部署模式需要填写集群中所有 member 的信息 initial-cluster-token: 初始化集群时使用的 token,随便写 initial-cluster-state: 初始化集群状态,可选的值为 new 或者 existing,通常采用 new # 编写 compose 文件 ubuntu:/data/containers/etcd# vi docker-compose.yaml --- version: '3' services: etcd: container_name: etcd-s1 image: quay.io/coreos/etcd:v3.5.12 command: /usr/local/bin/etcd --config-file=/var/lib/etcd/conf/etcd.conf.yml volumes: - ${DOCKER_VOLUME_DIRECTORY:-.}/data:/var/etcd - ${DOCKER_VOLUME_DIRECTORY:-.}/config/etcd.conf.yml:/var/lib/etcd/conf/etcd.conf.yml - "/etc/localtime:/etc/localtime:ro" ports: - 2379:2379 - 2380:2380 restart: always networks: app_net: driver: bridge ipam: driver: default config: - subnet: 172.238.238.0/24 ---
启动容器, 在 compose 文件目录
docker-compose up -d
root@ubuntu:/data/containers/etcd# docker-compose up -d WARNING: Some networks were defined but are not used by any service: app_net Creating network "etcd_default" with the default driver Creating etcd-s1 ... done root@ubuntu:/data/containers/etcd# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 24162db8e44b quay.io/coreos/etcd:v3.5.12 "/usr/local/bin/etcd…" 4 seconds ago Up 2 seconds 0.0.0.0:2379-2380->2379-2380/tcp, :::2379-2380->2379-2380/tcp etcd-s1
顺便测试下容器,用到 etcdctl 工具,下载参见参考文档:
root@ubuntu:~/etcd/etcd-v3.5.12-linux-amd64# ./etcdctl --endpoints=0.0.0.0:2379 --write-out=table endpoint health +--------------+--------+-------------+-------+ | ENDPOINT | HEALTH | TOOK | ERROR | +--------------+--------+-------------+-------+ | 0.0.0.0:2379 | true | 31.864411ms | | +--------------+--------+-------------+-------+ root@ubuntu:~/etcd/etcd-v3.5.12-linux-amd64# ./etcdctl --endpoints=0.0.0.0:2379 put foo bar OK root@ubuntu:~/etcd/etcd-v3.5.12-linux-amd64# ./etcdctl --endpoints=0.0.0.0:2379 get foo foo bar
走到这里,说明你的 etcd 单节点容器目前可用了,恭喜你。
3.goalng etcd 客户端实现
先看看具体的实现:
package main import ( "context" "fmt" "time" "go.etcd.io/etcd/client/v3" ) // demo, etcd client put/get func main() { cli, err := clientv3.New(clientv3.Config{ Endpoints: []string{"172.30.5.240:2379"}, DialTimeout: 5 * time.Second, }) if err != nil { // handle error! fmt.Printf("connect to etcd failed, err:%v\n", err) return } fmt.Println("connect to etcd success") defer cli.Close() // put ctx, cancel := context.WithTimeout(context.Background(), time.Second) _, err = cli.Put(ctx, "test", fmt.Sprintf("test-val: %v", time.Now().Format(time.RFC3339))) cancel() if err != nil { fmt.Printf("put to etcd failed, err:%v\n", err) return } // get ctx, cancel = context.WithTimeout(context.Background(), time.Second) resp, err := cli.Get(ctx, "test") cancel() if err != nil { fmt.Printf("get from etcd failed, err:%v\n", err) return } for _, ev := range resp.Kvs { fmt.Printf("%s:%s\n", ev.Key, ev.Value) } }
我的依赖 - go.mod:
module go-etcd go 1.19 require ( github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect go.etcd.io/etcd/api/v3 v3.5.15 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect go.etcd.io/etcd/client/v3 v3.5.15 // indirect // 这里需要注意版本问题,v3.3问题挺多,建议用3.5后的 go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.17.0 // indirect golang.org/x/net v0.23.0 // indirect golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/grpc v1.59.0 // indirect google.golang.org/protobuf v1.33.0 // indirect )
以下是运行结果:
connect to etcd success test:test-val: 2024-08-01T11:13:06+08:00
恭喜你,已经掌握 golang etcd 的客户端实现。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?