蚂蚁金服 RPC 框架 Sofa-Bolt 结构分析

转自:https://zhuanlan.zhihu.com/p/37260151

蚂蚁金服近期开源了研发多年的SOFA一篮子框架,其中就有一个非常核心的RPC框架,它叫Sofa-Bolt。小编今天花了近一天的时间仔细阅读研究它的源码,阅读过程中遇到了不少问题,蚂蚁金服的相关技术人员都非常耐心的及时解答了我的疑难。这里将我从中学到的知识点一并分享给大家。

Sofa-Bolt 基于开源的Netty框架,同时提供了服务器和客户端的实现。它的源码非常值得一读,结构简单,考虑周全,绝不是一个普通的玩具。它没有滥用设计模式,源码阅读起来比较直接,没有太多绕来绕去的复杂结构。

一个节点既可以同时既是RPC服务器又是客户端,作为客户端该节点需要其它节点提供服务,作为服务器它可以为其它节点提供服务。不过上面这张图并不是合理的结构,因为两个服务相互耦合了,我需要你,你也需要我,就成了鸡蛋问题。比较合理的结构一般如下图所示,它们之间不构成环。

通讯协议

通讯协议是客户端和服务器之间交流的语言,SOFA定义了自己的一套通讯协议,它的编码解码分为二层,第一层是消息体对象的二进制序列化,这部分默认由开源的Hessian协议库序列化完成,第二层是负责给序列化的消息体增加一系列包装字段,形成一个完整的消息。包括请求ID、消息体的长度、协议版本号和CRC32校验位等等

如果希望进一步优化网络性能,SOFA还提供了Snappy压缩协议,可以在现有的两层协议基础上增加第三层,能显著降低网络传输负担。压缩是时间换空间,提升网络性能的同时,它也会加重CPU计算,所以在使用时需要适当进行权衡。

连接池

客户端和服务器之间一般需要建立多个连接,但是也不能每个请求都建立一个连接。一般是通过维护一个连接池,限定最大连接数。客户端通过有限的连接来和服务器进行通信。

我们在使用Jedis客户端和Redis服务器进行通信时,也是通过连接池来获取连接的。Jedis的连接必须是线程独占的,因为它不是线程安全的。从连接池中获取连接时,其它线程就暂时拿不到这个连接了,待当前线程处理完毕后,要将连接归还给线程池,这样其它线程才可以继续使用这个连接。

Redis的客户端请求和应答是顺序性的,一问一答,所以请求和应答不需要唯一ID就可以建立起关联。

Sofa-Bolt 不一样,它的问答是乱序的,问和答之间是必须通过请求的唯一ID来建立起关联。Bolt的客户端是线程安全的,它可以同时传递多个请求,连接对象会维护一个正在处理的RPC请求对象字典。当客户端想要发起RPC请求时,它不是从连接池中摘出一个独占连接,而是随意选择一个连接来传递自己的请求,这个连接也可以被其它线程同时使用。

负载均衡

客户端提供了多种复杂均衡的实现,阿里默认使用带权重的随机算法(RandomLoadBalancer),此外还有

  1. ConsistentHashLoaderBalancer 一致性hash,客户端和服务器之间的连接关系(谁跟谁连)比较稳定
  2. LocalPreferenceLoadBalancer 本地环回地址优先,提升本机调用性能
  3. RoundRobinLoadBalancer 循环依次来
  4. WeightedRoundRobinLoadBalancer 带权重的循环依次来
  5. RandomLoadBalancer 这个是带权重的随机,阿里的默认使用

服务器线程模型

服务器采用传统netty多线程模型,一个acceptor线程专门用来接收连接,然后扔给io线程处理读消息并解码成请求对象,最后扔给业务线程池进行处理。

心跳

客户端和服务器之间会有定时心跳检测连接的存活,默认30s来一次。tcp的关闭是通过FIN包来通知对方的,如果因为网络问题,对方连FIN包都收不到,那么即使一边关闭了套接字,另一边可能还以为连接正常。所以心跳检测存活机制在长连接应用里非常普遍。如果客户端连续发了三次心跳都没有收到服务器的回复,那么就认为连接已经关闭。服务器也会有连接存活检测,如果一个客户端连接90s内没有任何消息进来,那么也认为该连接已经断开。服务器不会主动发送心跳消息。

双工通信

RPC一般是由客户端向服务器发起一个请求,然后收到服务器的应答。Sofa-Bolt 的RPC是双工通信,服务器也可以向客户端主动发起请求,它们共享一个TCP连接。TCP连接本身就是双工的,所以这也不算什么奇迹。只是服务器在什么业务场景需要向客户端主动发起请求,这个蚂蚁并没有进行详细说明。

客户端作为主动连接方,它要负责重连和发起心跳消息。服务器作为被动方,它不需要处理重连,如果连接断开,它就直接将连接从集合中移除就行,不需要做特殊的处理,但是它会检测心跳消息,如果在一定时间内连接通道没有任何消息到来,它就会主动关闭。

重连

客户端的重连策略是一个单独的模块,有两个地方会成为重连的入口。一个是正常连接断开触发channelInActive回调,另一个就是重连连接不能建立成功时需要进行重试。Sofa-Bolt 有一个单独的重连线程,所有需要重连的连接会被包装成一个任务塞进这个线程的任务队列,该线程不断地从队列里拿任务进行重连处理,如果重连失败会尝试再将任务重新包装进队列延后继续处理。默认是1s钟处理一个重连任务。

RPC连接是延迟建立的,它在第一次客户端发送RPC请求时尝试进行连接,如果连接失败,它会立即继续重连最多默认两次。如果三次尝试连接后还是没有建立成功,就向上层爆出异常。它不需要包装一个重连任务塞进ReconnectManager,因为后续客户端请求会继续触发连接。

单向消息

RPC通常是一应一答,客户端可以同步等待响应,也可以提供回调接口等待结果通知。Sofa-Bolt 除了提供应答模式之外,还提供了oneway单向消息,这种消息服务器收到后不用回复,客户端发送请求之后就立即返回了也不需要等待结果。

oneway消息一般用于不那么重要的日志类消息,它不能保证服务器一定能收到,所以此种业务消息应该是那种允许丢失的消息,形式上类似于UDP,它在牺牲可靠性的前提下能大幅提升消息的吞吐量。

消息追踪

Sofa-Bolt 提供了回调接口,方便监控系统可以对请求的调用状况进行分析。监控的客户端可以通过实现该接口,注册进RPC的客户端和服务器进行打点收集日志,然后发送到日志分析系统。

interface Tracer {void startRpc(SofaRequest request);void serverReceived(SofaRequest request);void serverSend(SofaRequest request, SofaResponse response, Throwable throwable);void clientReceived(SofaRequest request, SofaResponse response, Throwable throwable);...
}

总结

Sofa-Bolt 是一个成熟的比较复杂的RPC系统,这篇小文章只讲解了其中一部分,内部还有大量的实现细节有待去挖掘。

蚂蚁金服 RPC 框架 Sofa-Bolt 结构分析相关推荐

  1. 中国人自己的框架——蚂蚁金服RPC框架结构分析

    蚂蚁金服近期开源了研发多年的SOFA一篮子框架,其中就有一个非常核心的RPC框架,它叫SOFA-BOLT.小编今天花了近一天的时间仔细阅读研究它的源码,阅读过程中遇到了不少问题,蚂蚁金服的相关技术人员 ...

  2. 蚂蚁金服通信框架SOFABolt解析 | 协议框架解析

    2019新春支付宝红包技术大揭秘在线峰会将于03-07日开始,点击这里报名届时即可参与大牛互动. SOFA Scalable Open Financial Architecture 是蚂蚁金服自主研发 ...

  3. 深度分析蚂蚁金服RPC框架结构

    蚂蚁金服近期开源了研发多年的SOFA一篮子框架,其中就有一个非常核心的RPC框架,它叫SOFA-BOLT.今天花了近一天的时间仔细阅读研究它的源码,阅读过程中遇到了不少问题,蚂蚁金服的相关技术人员都非 ...

  4. 蚂蚁金服通讯框架学习一

    前  言 互联网领域的通信技术,有各式各样的通信协议可以选择,比如基于 TCP/IP 协议簇的 HTTP(1/2).SPDY 协议.WebSocket.Google 基于 UDP 的 QUIC 协议等 ...

  5. 仿蚂蚁金服AntV框架蚂蚁数据可视化F2 基金折线图、对比图(包含买卖点、自定义标签等,注释详尽)

    大家好,这次使用的是AntV的蚂蚁数据可视化F2框架,类似于蚂蚁基金的效果,包含买卖点.自定义标签等,代码如下: F2框架参考网址:https://antv-f2.gitee.io/zh/exampl ...

  6. 仿蚂蚁金服AntV框架蚂蚁数据可视化F2条形图、柱状图(注释详尽)

    大家好,这次使用的是AntV的蚂蚁数据可视化F2框架,类似于蚂蚁基金的效果,代码如下: F2框架参考网址:https://antv-f2.gitee.io/zh/examples/bar/basic# ...

  7. 仿蚂蚁金服AntV框架蚂蚁数据可视化F2饼图(注释详尽)

    大家好,这次使用的是AntV的蚂蚁数据可视化F2框架,类似于蚂蚁基金的效果,代码如下: F2框架参考网址:https://antv-f2.gitee.io/zh/examples/pie/donut# ...

  8. 蚂蚁金服分布式事务框架DTX源码学习

    文章目录 一.前言 二.DTX简介 三.角色 四.服务发起者与参与者DTX客户端启动流程 1.项目启动,创建dtx动态代理 2.初始化DtxClient客户端的init()方法 五.服务发起以及参与流 ...

  9. 蚂蚁金服的 Service Mesh 演进之道?

    蚂蚁金服在服务化上面已经经过多年的沉淀,支撑了每年双十一的高峰峰值.Service Mesh 作为微服务的一个新方向,在最近两年成为领域的一个大热点,但是如何从经典服务化架构往 Service Mes ...

  10. 干货 | 蚂蚁金服是如何实现经典服务化架构往 Service Mesh 方向的演进的?

    小蚂蚁说: 蚂蚁金服在服务化上面已经经过多年的沉淀,支撑了每年双十一的高峰峰值.Service Mesh 作为微服务的一个新方向,在最近两年成为领域的一个大热点,但是如何从经典服务化架构往 Servi ...

最新文章

  1. android圆形旋转菜单,而对于移动转换功能支持
  2. Tornado 类与类组合降低耦合
  3. 清华浙大年度学生最高奖,都颁向量子物理
  4. DataTables 表格固定栏使用方法
  5. 查看电脑python虚拟环境-Windows系统下,Python虚拟环境搭建
  6. Android之PowerManagerBatteryManager
  7. xp 无线连接 服务器,NPS配置无线策略XP能正常连接,WIN连接不成功
  8. HTML5 的知识分享(二):HTML5 的常用标签
  9. $emit传递多个参数_10年架构师深解java核心技术:方法参数+对象构造,确定不学?...
  10. 自定义汇编程序,Weaver和运行时的可插拔知识
  11. c语言超时自动退出,Golang实现for循环运行超时后自动退出的方法
  12. visio一分二的箭头_Microsoft Office Visio绘画双箭头直线的具体步骤介绍
  13. [心得]怪诞心理学精华笔记
  14. 产品策划流程体系、工具
  15. 智能手机 + 机器学习 = 个人终端的未来
  16. .net 大型药品进销存管理系统源码
  17. ShardingSphere(二)
  18. 2020款Macbook Pro忘了激活锁账户密码如何向苹果申请解锁
  19. Android系统手机的ROOT的那些事儿~ 附主流手机的ROOT图文教程和工具下载
  20. matlab 洛朗展开,将函数在圆环内展开成洛朗级数

热门文章

  1. python输入个人所得税计算_python实例个税计算
  2. 在Unity Shader中实现漫反射光照模型(逐顶点漫反射光照、逐像素漫反射光照、半兰伯特光照)
  3. 万王之王手游服务器维护,万王之王手游-KOK-官方网站-腾讯游戏-一个世界的重新开启...
  4. C语言刷题训练营-第一讲
  5. php访问80端口强制跳转443,nginx 80端口重定向到443端口
  6. Python图像处理库PIL的基本概念介绍(一)
  7. 微软超融合私有云测试05-Hyper-V故障转移群集部署
  8. jmeter+ant+jenkins接口自动化测试框架
  9. ORA-12514问题解决方法
  10. MTK6577手机有哪些 MT6577手机汇总