Transporter接口在包rafthttp中作为网络层核心接口之一,包含连接请求以及处理响应的Handler逻辑和提供发送消息的接口,以及包含对每个peer节点的维护操作,同时,也为etcd-raft模块架起通讯的桥梁。
结构体
type Raft interface {
//将指定的消息实例传递到底层的etcd-raft模块进行处理
Process(ctx context.Context, m raftpb.Message) error
IsIDRemoved(id uint64) bool//检测指定节点是否从当前集群中移除
ReportUnreachable(id uint64)//通知底层etcd-raft模块,当前节点与指定的节点无法连通
ReportSnapshot(id uint64, status raft.SnapshotStatus)//通知底层etcd-raft模块,快照数据是否发送成功
}
type Transporter interface {
Start() error //初始化操作
Handler() http.Handler//创建Handler实例,并关联到指定的URL上
Send(m []raftpb.Message) //发送消息
SendSnapshot(m snap.Message)//发送快照数据
AddRemote(id types.ID, urls []string)//在集群中添加一个节点时,其他节点会通过该方法添加该新节点消息
AddPeer(id types.ID, urls []string)//添加指定集群节点(自己除外)
RemovePeer(id types.ID) //移除集群指定节点
RemoveAllPeers() //移除所有的节点
UpdatePeer(id types.ID, urls []string)//修改节点信息
ActiveSince(id types.ID) time.Time //节点存活时长的统计
ActivePeers() int //处于活跃状态得节点数
Stop() //关闭所有连接
}
type Transport struct {
DialTimeout time.Duration //拨号超时的时间
DialRetryFrequency rate.Limit //拨号重试的频率
TLSInfo transport.TLSInfo //tls信息安全
ID types.ID //当前节点自己的ID
URLs types.URLs//当前节点与集群其他节点交互时使用的URL地址
ClusterID types.ID //当前节点所在的集群ID
//Raft是一个接口,其实现的底层封装了etcd-raft模块,当rafthttp.Transport收到消息之后,会将其交给raft实例进行处理。
Raft Raft
Snapshotter *snap.Snapshotter //负责管理快照文件
streamRt http.RoundTripper //stream消息通道中使用http.RoundTripper,实现了http.Transport,用来完成一个HTTP事务
pipelineRt http.RoundTripper//pipeline消息通道中使用http.RoundTripper,实现了http.Transport,用来完成一个HTTP事务
remotes map[types.ID]*remote//remotes中只封装了pipeline实例,remote主要负责发送快照数据,帮助新加入的节点快速追赶其他节点的数据。
peers map[types.ID]Peer//Peer接口是当前节点对集群中其他节点的抽象表示。对于当前节点来说,集群中其他节点在本地都会有一个Peer实例与之对应,peers字段维护了节点ID到对应Peer实例之间的映射关系。
pipelineProber probing.Prober//用于探测pipeline通道是否可用
streamProber probing.Prober //用于探测stream通道是否可用
}
rafthttp.Transport是rafthttp.Transporter接口具体实现,它提供了向对等端发送raft消息的功能,并且接受其他节点的消息。下面对Transport接口实现做进一步讲解。
Transport初始化
transport初始化在etcd方法StartEtcd启动etcd并在etcdserver方法NewServer初始化etcdserver时候完成。
func (t *Transport) Start() error {
//创建Stream消息通道使用http.RoundTripper实例,底层实际上是创建http.Transport实例
//这里创建连接的超时时间(根据配置指定),读写请求的超时时间(默认5s),keepAlive时间(默认30s)
t.streamRt, err = newStreamRoundTripper(t.TLSInfo, t.DialTimeout)
//创建Pipeline消息通道使用http.RoundTripper实例,底层实际上是创建http.Transport实例
//创建连接的超时时间(根据配置指定),keepAlive时间(默认30s),与stream不同的是读写请求的超时时间设置为永不过期
t.pipelineRt, err = NewRoundTripper(t.TLSInfo, t.DialTimeout)
//初始化remotes和peers两个map字段
t.remotes = make(map[types.ID]*remote)
t.peers = make(map[types.ID]Peer)
//初始化prober实例用于探测pipeline和stream消息是否可用
t.pipelineProber = probing.NewProber(t.pipelineRt)
t.streamProber = probing.NewProber(t.streamRt)
if t.DialRetryFrequency == 0 {
t.DialRetryFrequency = rate.Every(100 * time.Millisecond)