续约协程的问题
来源:4-8 lease租约实现kv过期
慕桂英5168734
2020-02-12
第一份代码
package main
import (
"context"
"fmt"
"go.etcd.io/etcd/clientv3"
"time"
)
func main() {
config := clientv3.Config{
Endpoints: []string{"127.0.0.1:2379"},
DialTimeout: 5 * time.Millisecond,
}
client, err := clientv3.New(config)
if err != nil {
fmt.Println(err.Error())
}
lease := clientv3.NewLease(client)
// 申请一个五秒过期的租约
grant, err := lease.Grant(context.TODO(), 5)
if err != nil {
fmt.Println(err)
}
aliveChain, err := lease.KeepAlive(context.TODO(), grant.ID)
kv := clientv3.NewKV(client)
putValue, err := kv.Put(context.TODO(), "/cron/lock/lock1", "ticker", clientv3.WithLease(grant.ID))
if err != nil {
fmt.Println(err)
}
fmt.Println("插入的revision=", putValue.Header.Revision)
for {
value, err := kv.Get(context.TODO(), "/cron/lock/lock1")
if err != nil {
panic(err.Error())
}
if len(value.Kvs) == 0 {
fmt.Println("key已经过期")
break
}
time.Sleep(time.Second)
fmt.Printf("获取的值=%v\n", value.Kvs)
}
// 续约协程
go func() {
for {
select {
case nn := <-aliveChain:
if nn == nil {
fmt.Println("续约失败", nn)
} else {
fmt.Println("续约中")
}
}
}
}()
}
这样的代码实现,只会打出 获取的值信息,类似如下输出
插入的revision= 38
获取的值=[key:"/cron/lock/lock1" create_revision:38 mod_revision:38 version:1 value:"ticker" lease:7587844330916674737 ]
获取的值=[key:"/cron/lock/lock1" create_revision:38 mod_revision:38 version:1 value:"ticker" lease:7587844330916674737 ]
===============分割线==============
第二份代码
package main
import (
"context"
"fmt"
"go.etcd.io/etcd/clientv3"
"time"
)
func main() {
config := clientv3.Config{
Endpoints: []string{"127.0.0.1:2379"},
DialTimeout: 5 * time.Millisecond,
}
client, err := clientv3.New(config)
if err != nil {
fmt.Println(err.Error())
}
lease := clientv3.NewLease(client)
// 申请一个五秒过期的租约
grant, err := lease.Grant(context.TODO(), 5)
if err != nil {
fmt.Println(err)
}
aliveChain, err := lease.KeepAlive(context.TODO(), grant.ID)
// 续约协程 (NOTE: 仅仅该函数的位置调整了)
go func() {
for {
select {
case nn := <-aliveChain:
if nn == nil {
fmt.Println("续约失败", nn)
} else {
fmt.Println("续约中")
}
}
}
}()
kv := clientv3.NewKV(client)
putValue, err := kv.Put(context.TODO(), "/cron/lock/lock1", "ticker", clientv3.WithLease(grant.ID))
if err != nil {
fmt.Println(err)
}
fmt.Println("插入的revision=", putValue.Header.Revision)
for {
value, err := kv.Get(context.TODO(), "/cron/lock/lock1")
if err != nil {
panic(err.Error())
}
if len(value.Kvs) == 0 {
fmt.Println("key已经过期")
break
}
time.Sleep(time.Second)
fmt.Printf("获取的值=%v\n", value.Kvs)
}
}
紧紧是调整了协程的代码位置,输出中会打出“续约中”,形如下列输出
续约中
插入的revision= 40
获取的值=[key:"/cron/lock/lock1" create_revision:40 mod_revision:40 version:1 value:"ticker" lease:7587844330916674753 ]
续约中
获取的值=[key:"/cron/lock/lock1" create_revision:40 mod_revision:40 version:1 value:"ticker" lease:7587844330916674753 ]
获取的值=[key:"/cron/lock/lock1" create_revision:40 mod_revision:40 version:1 value:"ticker" lease:7587844330916674753 ]
===============分割线==============
问题: 为什么两份代码都能成功续约,都不会中断,但是第一份中没有打出“续约中”字样,仅仅是协程函数的代码位置的差异?
麻烦老师指点,多谢
写回答
1回答
-
小鱼儿老师
2020-02-15
同学好,第一份代码的因为for循环持续执行,所以没有机会执行到创建后面的golang协程。
00
相似问题