在写etcd-raft的leader选举的那篇文章时,每次牵扯到消息接收和发送都用”接收到消息”、“把消息发送”出去这样的字眼给代替了,感觉有那么一点的别扭,这节主要描述下etcd-raft的消息发送和接收。
先附上一副关键struct类成员关系图,先对这个交互复杂度在心里有个数^_^
在介绍信息交互流程之前先介绍几个比较关键的结构体类型以及结构体里面关键嵌入成员:
EtcdServer :
// etcd-2.3.7/etcdserver/server.go
type EtcdServer struct {
// etcdserver中用于与raft模块交互的接口
r raftNode
// ...
}
raftNode:
// etcd-2.3.7/etcdserver/raft.go
type raftNode struct {
//...
// 指向raft.node,用于用于raft协议相关消息的处理和生成
raft.Node
// ...
// transport specifies the transport to send and receive msgs to members.
// 最终指向rafthttp.Transport
transport rafthttp.Transporter
// ...
}
raft.node:
// etcd-2.3.7/raft/node.go
// node is the canonical implementation of the Node interface
type node struct {
// 从peer端收到的消息会通过recvc传给raft算法处理
// 从客户端收到的写请求会通过propc传给raft算法处理
propc chan pb.Message
recvc chan pb.Message
// ...
// 通过readyc channel把已经被raft处理完毕待发送的消息传给raftNode,raftNode在start会select到r.ready()上
readyc chan Ready
// ...
}
rafthttp.Transport:
// etcd-2.3.7/rafthttp/transport.go
type Transport struct {
// 当前peer连接通过streamReader连接其他peer的超时时间
DialTimeout time.Duration // maximum duration before timing out dial of the request
// ...
// 当前raft节点的id,以及url
ID types.ID // local member ID
URLs types.URLs // local peer URLs
// ...
// 指向EtcdServer
Raft Raft // raft state machine, to which the Transport forwards received messages and reports status
// ...
// 每个peer代表一个集群中的raft节点,peer之间通过streamReader以及streamWriter相互通信,最终直到一个peer对象
peers map[types.ID]Peer // peers map
// ...
}
peer:
// etcd-2.3.7/rafthttp/peer.go
type peer struct {
// id of the remote raft peer node
id types.ID
// 指向EtcdServer,用于在收到消息时把消息内容传给EtcdServer的Process函数
r Raft
// ...
// msgAppV2Writer与writer等待peer的连接,用于用于发送消息
msgAppV2Writer *streamWriter
writer *streamWriter
// 发送snap时,文件内容比较多时才会用到
pipeline *pipeline
// ...
sendc chan raftpb.Message
// streamReader从该peer的连接中读到非写请求消息时会通过recvc发送给当前peer对象的宿主goroutine,然后通过peer.r.Process传给EtcdServer
recvc chan raftpb.Message
// streamReader从该peer的连接中读到slave转发给master的写请求
propc chan raftpb.Message
// ...
}
streamReader:
// etcd-2.3.7/rafthttp/stream.go
type streamReader struct {
// ...
// recvc以及propc与peer中同名变量指向同一个对象,是peer在startPeer中创建streamReader传入的
recvc chan<- raftpb.Message
propc chan<- raftpb.Message
// ...
}
streamWriter:
// streamWriter writes messages to the attached outgoingConn.
type streamWriter struct {
// ...
// 指向EtcdServer
r Raft
// ...