config := etcdv3.Config{
Endpoints: []string{"invalid:2379"},
DialTimeout: 2*time.Second,
}
client, err := etcdv3.New(config)
if err != nil {
panic(err)
}
...
// keep alive
lease, err := client.Grant(ctx, ttl)
if err != nil {
panic(err)
}
执行以上代码按道理,是会返回错误的,但是在项目部署阶段却发现代码运行到lease, err := client.Grant(ctx, ttl)
这个地方的时候会阻塞在这边,没有任何错误的返回。
初步解决办法
config := etcdv3.Config{
Endpoints: []string{"invalid:2379"},
DialTimeout: 2*time.Second,
}
client, err := etcdv3.New(config)
if err != nil {
panic(err)
}
...
timeoutCtx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
_, err = cli.Status(timeoutCtx, srv.EtcdAddrs[0])
if err != nil {
return err
}
// keep alive
lease, err := client.Grant(ctx, ttl)
if err != nil {
panic(err)
}
这样按照预期的返回错误了,但是不够优雅,而且这么做就等于是固定了etcd的数量,也不灵活
后来在github官方仓库翻,看到一篇issue,讲的就是这个问题#9877
,虽然说是长连接,但是错误的连接总得报错是吧
最终的解决方案
config := etcdv3.Config{
Endpoints: []string{"invalid:2379"},
DialTimeout: 2*time.Second,
DialOptions: []grpc.DialOption{grpc.WithBlock()},
}
client, err := etcdv3.New(config)
if err != nil {
panic(err)
}
这样就能按照预期,输入错误的地址,会返回错误...Error while dialing: dial tcp xxx:xxx: connect: connection refused...
的错误信息