首页 > 其他分享 >etcd网络模块解析

etcd网络模块解析

时间:2023-06-27 19:22:25浏览次数:34  
标签:pipeline etcd rafthttp 模块 格式 peer raft 解析

1. RaftHttp模块介绍

在etcd里raft模块和网络模块是分开的,raft模块主要负责实现共识算法,保证集群节点的一致性,消息的发送和接收则交给raftHttp网络模块来处理,由上层应用模块来进行协调交互和消息传递。  

1.1. 整体结构图

  0   (1)当raft模块发生了状态变化时,会把变化的消息封装到ready对象中,上层应用模块通过监听ready的channel能够获取到对应的消息,然后调用网络层的send方法来发送到其它节点上; (2)send方法这里会根据消息的类型做一个分发,如果是快照的消息则写入到pipeline的msgc channel中,其它消息则都写入到streamWriter的msgc channel中; (3)streamWriter启动时会创建一个goroutine,它会监听connc管道上是否有网络连接对象conn(这个是在对方发起get请求建立起来的网络连接),如果有则获取并使用它来作为底层传递对象,监听msgc通道上的消息,如果有消息则获取并通过conn进行发送,如果connc管道上没有则等待; (4)streamReader启动时会进行一个回拨与peer端建立一条网络连接,比如B节点会发起一个GET请求到A节点,建立一条网络连接,A节点会把这条网络连接放入到connc管道中,供A节点的streamWriter进行写入使用,B节点则是从这条网络连接里读数据,有点类似单向管道;同理A节点的streamReader在启动时也会发起GET请求到B节点从而建立网络连接,此时这条网络是A节点进行读取,B节点进行写入; (5)对于快照的数据,v3版本的是使用snapSender来进行发送,创建post请求通过pipeline的transport来进行发送;之前的版本则是封装为一个快照消息分发到pipeline的msgc的channel中,pipeline在启动时会创建4个goroutine来监听msgc管道里的消息,如果有则取出并创建post请求通过pipeline transport发送出去; (6)streamReader从stream pipeline中读到数据时将其进行反序列化为消息,然后根据消息的类型分别放到propc或recvc管道中,这样做区分的原因是因为MsgProp的消息处理的耗时可能比较长,所以单独放到一个管道中去,这样不阻塞其它消息的处理,这两个管道分别会有个goroutine进行读取并调用raft对象的Process函数将其传入到raft模块里去处理; (7)snapshotHandler是一个gateway的方式接收发过来的post请求,接收快照数据保存到本地然后通知raft状态机进行处理; (8)streamHandler也是一个gateway的方式接收streamReader发送过来的GET请求,并将该网络连接塞入到connc管道中,供streamWriter进行数据写入; (9)stream的http transport:在创建http transport时传入的read和write的超时时间是5,因为stream通道传输的消息数据一般都比较小; (10)pipeline的http transport:在创建http transport时传入的read和write的超时时间是0,因为快照数据比较多,读写的时间也比较长;  

1.2. 关键数据结构分析

  0   rafthttp.Transport:网络模块数据结构,里面维护了多个进行网络交互的流对象,通过这个对象可以添加peer和发送数据;   http.Transport:go的http库,rafthttp.transport也是通过创建它来进行数据发送和读取,它会去维护tcp连接,并且管理空闲连接;rafthttp里创建了两个http.Transport对象,一个是stream用的,一个是pipeline用的;   rafthttp.remote:里面也封装了pipeline,使用pipeline http transport网络发送数据,主要是帮助新加入的成员进行数据追赶。当peer的网络不可用时,如果此时有remote的则也会使用remote的网络连接来进行发送数据;   rafthttp.peer:peer代表对端,维护的是向peer发送数据和接收peer数据的网络流对象;   rafthttp.pipeline:用以发送快照;   rafthttp.streamWriter:rafthttp.peer对象的输出流,通过它向peer端发送数据;   rafthttp.streamRader:rafthttp.peer对象的输入流,通过它从peer端接收数据;  

2. 关键流程分析

2.1. raftExample的网络模块初始化

  0  

2.2. 启动peer流程

  0  

2.3. streamWriter启动流程

  0  

2.4. streamReader启动流程

  0  

3. 传输格式

在代码中,其实我们可以看到streamReader和streamWriter都分别有两个对象的。 streamWriter:writer和msgAppV2Writer streamReader:msgAppReader和msgAppV2Reader 这两个对象的关键不同点就是encode和decode的不同,因为底层传输字节格式不一样,所以需要这样区分开来。  

3.1. msgApp格式

Message压缩后发送的格式: 0   比较简单,直接就是写入消息长度,然后接着是压缩后的数据。解压时先读取消息长度,然后读取指定长度的数据进行反序列化为Message格式。  

3.2. msgAppV2格式

根据Message的消息类型分为3种格式存储。  

3.2.1. linkHeartbeatMessage类型的消息

只有一个字节,字节值为uint8的0  

3.2.2. 数据格式是msgTypeAppEntries的

符合这种格式的条件是编码器保存的index、term和logTerm跟Message中的index、term和logTerm一致,否则解码器对象里保存的这些值补充到Message的Entry里就是错的了,对于解码器对象里index等变量的维护逻辑与编码器里的一致。   0   解压时按照这种格式读出来,然后填充上解码器对象里的index、term和logTerm值即可。 msgAppV2格式的压缩优化要点:消息中携带的多个entry的index、Term等字段大多数场景都是一样的。当有多个Entry时,它可以节省index、Term和LogTerm这些字段的重复传输,因为在实际使用场景,大概率这些字段都是重复的,所以在encode时只需要保存一份即可,解压时再补上去就行,相比msgApp的直接整个序列化的方式,它传输的字节数要少得多。  

3.2.3. 非linkHeartbeatMessage和msgTypeAppEntries格式

这种格式类型命名为msgTypeApp,压缩方式与msgApp一样,只不过前面多了个字节,值为uint8的2。  

4. 网关URL映射处理逻辑

 
URL前缀 映射处理对象 请求举例 说明
/raft pipelineHandler POST /raft 只接收POST请求,接收数据后反序列化为Message对象,然后传入到raft模块处理
/raft/probing probingHandler GET /raft/probing 收到请求后响应消息,并且带上当前响应时间戳,表示探测成功
/raft/stream/ streamHandler GET /raft/stream/message/{localID}(V1的格式) GET /raft/stream/msgapp/{localID}(V2的格式) 只接收GET请求,用来建立stream网络连接
/raft/snapshot snapHandler POST /raft/snapshot 只接收POST请求,接收到数据后反序列化为Message对象,检查消息类型是否为快照类型,如果不是则返回错误信息,如果是则保存快照数据到本地并传到raft模块进行处理
   

标签:pipeline,etcd,rafthttp,模块,格式,peer,raft,解析
From: https://www.cnblogs.com/luohaixian/p/17509742.html

相关文章

  • 菜鸟学习Spring——SpringMVC注解版解析不同格式的JSON串
    一、概述    不同格式的JSON串传到后台来实现功能这个是我们经常要做的一件事,本篇博客就给大家介绍四种不同的JSON串传到后台后台如何用@RequestBody解析这些不同格式的JSON串的。二、代码展示需要引用的jar包1.xml配置  Web.xml1.<?xmlversion="1.0"encoding="UTF-8......
  • Python logging模块(转载)
    Pythonlogging模块日志级别CRITICAL=50#FATAL=CRITICALERROR=40WARNING=30#WARN=WARNINGINFO=20DEBUG=10NOTSET=0#不设置默认级别为warning,默认打印到终端importlogginglogging.debug('调试debug')logging.info('消息info')logging.warnin......
  • RT-Thread 正点原子阿波罗STM32F429IGT6-软件IIC控制I/O扩展模块PCF8574T(踩坑)
    第一步:在RT-ThreadSettings中打开I2C设备驱动,Ctrl+S保存 第二步:在drivers->board.h中进行配置,取消BSP_USING_I2C2的注释,并根据说明定义好引脚; 第三步:对引脚进行初始化,这里可使用CubeMX进行生成; 第四步:根据设备名查找设备 第五步:调用 rt_i2c_transfer 发......
  • BOSHIDA DC电源模块输入电压与体积的关系
    BOSHIDADC电源模块输入电压与体积的关系DC电源模块是一种将交流电转换为直流电的电源设备,可以为各种家庭电器和电子设备提供稳定的直流电供电。输入电压是DC电源模块最基本的参数,也是使用者最需要关注的参数之一,因为它能决定这个设备的适用范围。在选择DC电源模块时,通常需要根据......
  • .NET Core 获取小程序手机号并解析
    方法一:1.小程序提供微信用户授权后的code,用户手机号的加密数据和iv。2.使用code换取 sessionkey。3. 解密用户手机号的加密数据。参考代码///<summary>///获取openid,sessionkey///</summary>///<paramname="appID"></param......
  • 《深入解析 css》笔记
    第一章:层叠、优先级和继承1.优先级:!important>行内样式>id选择器>类选择器>标签选择器2.两条经验法则:选择器少用id;少用!important。3.使用inherit属性使元素属性继承自父元素,方便修改。4.使用简写属性的时候会默认给细化的属性赋默认值,如标签h1的样式font:32pxarial;默......
  • ABP - 缓存模块(2)
    1.缓存模块源码解析个人觉得ABP分布式缓存模块有三个值得关注的核心点。首先是AbpRedisCache类继承了微软原生的RedisCache,并通过反射的方式获取RedisCache的私有方法对RedisCache进行扩展,实现了ABP分布式缓存中的批量操作方法。为什么要这么做呢?因为基于Redis缓......
  • JS(函数、作用域、预解析)
    一函数的概念在JS里面,可能会定义非常多的相同代码或者功能相似的代码,这些代码可能需要大量重复使用。虽然for循环语句也能实现一些简单的重复操作,但是比较具有局限性,此时我们就可以使用JS中的函数。函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量......
  • 在pod内,如何通过curl命令来解析一个域名的地址?
    最近在测试kubernetes的这个apiserver的域名解析出来的地址,到底是多少,然后呢,就进入到一个容器里面,发现没有ping、nslookup、host、dig、nc、wget命令 如何知道这个service名字是解析到了什么呢? 因为在pod内,使用coredns解析,就是解析service的名字 后来查了以下,可以通过c......
  • 基于DSP的设备振动信号的采集和处理模块研发总结
    前记 在能源领域,由于很多地方都是无人值守,设备故障检测是一个必须面对的问题。笔者通过最近几个行业案例了解到,由于很多设备发生故障时候会产生特定频谱的声音,所以该行业对振动监测的需求特别强烈,由于涉及到个性化的方案定制和处理,市面上此类的解决方案特别少。笔者希望把最近的......