etcd server启动的流程
【github.com/coreos/etcd@v3.3.18+incompatible/embed/etcd.go:93】
1、检查配置
2、创建Etcd实例
3、开始监听节点node
4、开始监听客户端client
5、根据wal日志初始化作为集群成员
6、获取PeerURLsMap(peerUrl 与 etcd name对应的map)以及cluster token
7、生成new etcdServer所需的的ServerConfig结构体
8、创建EtcdServer实例,初始化EtcdServer
1、分配内存空间
2、检查是否有data数据目录
3、检查是否有快照目录
4、根据数据目录data是否有预写日志haveWAL和node状态是否是NewCluster的不同,调用不同函数创建raft node
5、初始化作为server的状态
6、初始化集群leader状态
7、实例化EtcdServer对象,作为提供服务方,包含了raft node
8、初始化租期lessor,设置定时租期
9、初始化多版本并发控制mvcc
10、启动http处理handler,等待peer的连接
9、进入主循环(e.Server.Start()-->(s *EtcdServer) run()),等待处理etcd事件
1、初始化
1、从raft storage中获取快照,通过snapshot恢复store中完整状态
2、创建fifo调度队列FIFOScheduler
3、raft初始化响应事件处理raftReadyHandler(更新leader状态updateLeadership,更新commit index updateCommittedIndex)
4、启动raftNode,s.r.start(rh)
5、初始化etcdProcess参数,包括任期Term,commit日志下标Index等参数值
2、进入for循环等待处理各种etcd事件
1、case ap := <-s.r.apply()。当写事务已经被集群中超过半数的raft node确认过并且保存到WAL日志后,raftNode会触发apply()事件,进而执行applyAll方法进行处理。applyAll方法中会执行真正的写操作修改Etcd数据库内容
1、s.r.apply()
2、s.applyAll(&ep, &ap)
3、s.applyEntries(ep, apply)
4、s.apply(ents, &ep.confState)
5、s.applyEntryNormal(&e)
6、s.w.Trigger(req.ID, s.applyV2Request(req))
func (s *EtcdServer) applyV2Request(r *RequestV2) Response {
switch r.Method {
case "POST":
return s.applyV2.Post(r)
case "PUT":
return s.applyV2.Put(r)
case "DELETE":
return s.applyV2.Delete(r)
case "QGET":
return s.applyV2.QGet(r)
case "SYNC":
return s.applyV2.Sync(r)
default:
return Response{Err: ErrUnknownMethod}
}
}