在 ETCD 源码学习过程,不会讲解太多的源码知识,只讲解相关的实现机制,需要关注源码细节的朋友可以自行根据文章中的提示,找到相关源码进行学习。
服务端监听某个 key 或某个范围 key 变化,当被监听的 key 的值有任何变动,都会主动通知客户端(变更的版本号>指定版本号)。
主要文件
/etcd/clientv3/watch.go
结构图
主要数据结构
//对外提供 Watch 接口,同时负责关闭 grpcStream 的流程。
type watcher struct {
//访问服务的RPC客户端
remote pb.WatchClient //etcdserver/etcdserverpb/rpc.pb.go
...
// key=>grpcStream
streams map[string]*watchGrpcStream
lg *zap.Logger
}
/*
1.实例化过程中,会创建 WatchClient, 这个 WatchClient 用于和服务端进行数据传输。同时会启动一个 goroutine 用于接收服务端的消息。
2.管理 watcherStream 关闭,创建等流程,
3.启动一个 goroutine 用于处理 reqc、respc 等管道的消息。
4.分发事件给所有监听者。
*/
type watchGrpcStream struct {
owner *watcher
remote pb.WatchClient
....
//watchID=>watcherStream, 一个长连接
substreams map[int64]*watcherStream
//等待与服务器建立连接的 watcherStream
resuming []*watcherStream
//客户端发起 watch 请求会被追加到管道
reqc chan watchStreamRequest
//服务端的响应追加到该管道
respc chan *pb.WatchResponse
....
resumec chan struct{}
}
/*
主要用于管理 watcheRequest 与各个管道之间的数据传输关系。
管道outc、recvc、buf 之间的关系是:
(1)watchClient会有个goroutine 用于接收服务端的消息,并将这个消息追加到recvc 管道,
(2)如果 recvc 中有数据,会读取出来然后追加到buf缓冲中。
(3)如果 buf 不为空,会将消息发送给 outc, 客户端通过该管道,接收服务端的响应。
*/
type watcherStream struct {
//记录用户的请求实例