Thrift/RPC学习分享

Thrift/RPC学习分享

Thrift/RPC学习分享_第1张图片
一个完整RPC调用链路

  1. 客户端调用client内的方法,同时传入对应参数。这个client是公司内部封装了很多实现的细节。并且有@ThriftClient注解把指定路径下的类扫描到到容器当中。
  2. client调用对应的client-stub,并且把封装好的参数传入
  3. client去对应的服务中心拉取ipList(这个过程被叫做服务发现和路由寻址
  4. 由负载均衡机制选取一个合适的ip(这里面可以是先一些算法,比如哈希一致、轮询、加权轮询
    1. 轮询:好处是实现比较简单,坏处是,性能好性能差的机器收到的请求量相同
    2. 加权轮询:公司采用的方法,针对性能好的机器分配更多的请求
    3. 一致性哈希:可以应对某些特殊的情况,比如通过一致性哈希走小流量
    4. 最小连接:选择压力最小的服务器
  5. 执行一个调用链。在这个调用链里,可以实现熔断、降级、服务鉴权等等
  6. 调用上下文序列化,并且通过不同RPC的协议编码(比如thrift中的编码)发送至网络通信框架(这个时候就是TCP、UDP来做事了)
  7. 服务端接收到对应的请求,先通过RPC协议,反序列化、也要执行调用链,最后通过对应的service处理请求,把结果写回。

熔断、降级、限流

  1. 熔断:A调用B,B出错,导致A受影响,这个时候就需要熔断,让A不再调用B,防止系统雪崩
  2. 降级:保留核心功能,让非核心功能暂时不可用。属于人为操作
  3. 限流:当上游调度的速度超过自身服务速度,就采用限流的策略应对
    1. 令牌算法:定期往令牌桶中放置令牌,上游拿到令牌就允许调用,没拿到令牌就不允许调用。应对突发情况比桶算法优秀。
    2. 桶算法:桶的大小恒定,出桶的速率恒定,超过桶的量就丢弃
    3. 固定/滑动窗口算法:定一个窗口计数器,限定时间内,这个计数器没有减到0就允许访问。

Thrift构造

  1. 首先是构造一个proxy代理,因为RPC的初衷就是简单。dubbo没用过,但是公司的thrift是通过生成一个client,在这个client里面封装了所有调用远端的细节的。
  2. 服务发现:准确来说服务发现本身并不属于RPC的范畴。公司用的是consul,其他的还有zookeeper等,公司本身使用加权轮询来选择对应的ip
  3. RPC的路由与负载均衡
  4. 接收请求–>请求校验–>路由策略–>负载均衡。
    • Example:实际场景,当我们上线一个需求的时候,是不是想着灰度发布,因为想用 小流量来验证项目的正常流转。这个时候就可以通过IP路由选择来做这个事情。众所周知,server以集群的方式提供服务,在client调用server时候,会先取出一个ipList。这个时候我们针对这个ip做一个筛选就行了。比如上次一面问我,怎么做到,让一个client的请求让一个server来处理,这里就可以在路由这一层做。使用哈希一致性算法,固定打到某个ip上去。
    • 负载均衡:
      • 轮询
      • 随机
      • 加权
      • 最少连接
4. 值得注意的是,通常在负载均衡之前还有一个filter层,做一些筛选,比如根据env的信息做一些筛选。但是公司好像没做这一层。
  1. RPC在连接这一层。通常使用TCP的keep-alive,和应用层的心跳机制来保证连接。
  2. 首先建立长连接
  3. keep-alive这一层,默认2h没有数据传输,就关闭连接。
  4. 心跳机制是多久没发消息直接关闭连接。
  5. 在客户端发送信息之前,或者在服务端调用service-stb调用server执行的时候,会执行一条调用链。
  6. 比如公司实现一些熔断的操作
  7. 一些服务鉴权的操作(之前是一个假的鉴权,现在变成一个真的鉴权)

序列化和反序列化

在网络中传输只能是二进制,因此序列化就是对象 -> 二进制的过程
thrift序列化的协议有 compact、json、binary
在公司的thrift序列化协议通常使用的是
binary序列化格式
Thrift/RPC学习分享_第2张图片

  1. 消息头部
    1. message_type:
      1. oneWay:客户端消息,不期待服务器响应(非阻塞)
      2. call:客户端消息,期待服务器响应
      3. replay:服务端消息,正常响应
      4. exception:服务端消息,出现异常
    2. msg_id:消息的序列号
  2. 消息体:
    1. 字段类型
    2. 字段长度
    3. 字段值
    4. 字段序号
    5. 如果是定长消息就是 k-v的形式
    6. 如果是不定长的就是 k-l-v
RPC与HTTP

对于RPC的理解:
1. RPC的思想
2. RPC的协议
3. RPC的实现方式

  1. RPC的本质是一种思想,就是调用远程的方法就像调用本地的方法一样。
    如果只是在聊协议这个概念
  2. 首先要明确什么是协议:协议就是大家约定好,用什么格式写数据,用什么格式压缩数据,按照这个协议大家实现数据的通信。而HTTP和各种各样的RCP协议本质上就是在应用层的,定义了不同消息格式的通信协议
  3. RPC的实现方式:在这个实现方式上我们再聊聊RPC和HTTP不同的地方。
    1. 首先看域名和IP地址,在HTTP上是通过DNS解析拿到对应的域名的(其实本质上DNS解析也是一种服务发现的实现方式),而在RPC的层面,通常都会通过服务发现在公司用的是Consul。
    2. 对于http2,采用的是二进制来序列化来做序列化,但是对于传统的http1.1是通过Json来做序列化,而RPC的序列化可能更加灵活,用protobuf、binary来做序列化相对来说说损耗更小,性能更好。
关于序列化与反序列化

首先弄明白序列化、反序列化是什么

  1. 比如一个java对象,你想传输是不可能直接传输一个Java对象的,计算机只认二进制。所以把一个对象转化成一个字节序列的过程叫做序列化。
  2. 把一个字节序列反序列化成一个对象,叫做反序列化
    应用场景
  3. 当你需要把你的对象在网络上传递的时候
  4. 当你需要把你的对象保存成文本格式的时候
常见的序列化反序列化手段
  1. XML:文本结构的序列化手段
  2. JSON:文本结构的序列化手段
  3. Protobuf:谷歌开发的二进制序列化
  4. thrift binary:公司采用的二进制序列化

你可能感兴趣的:(rpc,学习,网络协议)