续约协程的问题

来源: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协程。

0
0

Go语言开发分布式任务调度 轻松搞定高性能Crontab

分布式系统设计+高并发细节处理,一次性让你“晋级”到位

1136 学习 · 177 问题

查看课程