深度分析蚂蚁金服RPC框架结构(深度分析蚂蚁金服rpc框架结构)
ccwgpt 2024-09-21 13:32 22 浏览 0 评论
专注于Java领域优质技术,欢迎关注
作者: 老钱 码洞
蚂蚁金服近期开源了研发多年的SOFA一篮子框架,其中就有一个非常核心的RPC框架,它叫SOFA-BOLT。今天花了近一天的时间仔细阅读研究它的源码,阅读过程中遇到了不少问题,蚂蚁金服的相关技术人员都非常耐心的及时解答了我的疑难。这里将我从中学到的知识点一并分享给大家。
SOFA-BOLT基于开源的Netty框架,同时提供了服务器和客户端的实现。它的源码非常值得一读,结构简单,考虑周全,绝不是一个普通的玩具。它没有滥用设计模式,源码阅读起来比较直接,没有太多绕来绕去的复杂结构。
一个节点既可以同时既是RPC服务器又是客户端,作为客户端该节点需要其它节点提供服务,作为服务器它可以为其它节点提供服务。不过上面这张图并不是合理的结构,因为两个服务相互耦合了,我需要你,你也需要我,就成了鸡蛋问题。比较合理的结构一般如下图所示,它们之间不构成环。
通讯协议
通讯协议是客户端和服务器之间交流的语言,SOFA定义了自己的一套通讯协议,它的编码解码分为二层,第一层是消息体对象的二进制序列化,这部分默认由开源的Hession协议库序列化完成,第二层是负责给序列化的消息体增加一系列包装字段,形成一个完整的消息。包括请求ID、消息体的长度、协议版本号和CRC32校验位等等
如果希望进一步优化网络性能,SOFA还提供了Snappy压缩协议,可以在现有的两层协议基础上增加第三层,能显著降低网络传输负担。压缩是时间换空间,提升网络性能的同时,它也会加重CPU计算,所以在使用时需要适当进行权衡。
连接池
客户端和服务器之间一般需要建立多个连接,但是也不能每个请求都建立一个连接。一般是通过维护一个连接池,限定最大连接数。客户端通过有限的连接来和服务器进行通信。
我们在使用Jedis客户端和Redis服务器进行通信时,也是通过连接池来获取连接的。Jedis的连接必须是线程独占的,因为它不是线程安全的。从连接池中获取连接时,其它线程就暂时拿不到这个连接了,待当前线程处理完毕后,要将连接归还给线程池,这样其它线程才可以继续使用这个连接。
Redis的客户端请求和应答是顺序性的,一问一答,所以请求和应答不需要唯一ID就可以建立起关联。
Bolt不一样,它的问答是乱序的,问和答之间是必须通过请求的唯一ID来建立起关联。Bolt的客户端是线程安全的,它可以同时传递多个请求,连接对象会维护一个正在处理的RPC请求对象字典。当客户端想要发起RPC请求时,它不是从连接池中摘出一个独占连接,而是随意选择一个连接来传递自己的请求,这个连接也可以被其它线程同时使用。
负载均衡
客户端提供了多种复杂均衡的实现,阿里默认使用带权重的随机算法(RandomLoadBalancer),此外还有
- ConsistentHashLoaderBalancer 一致性hash,客户端和服务器之间的连接关系(谁跟谁连)比较稳定
- LocalPreferenceLoadBalancer 本地环回地址优先,提升本机调用性能
- RoundRobinLoadBalancer 循环依次来
- WeightedRoundRobinLoadBalancer 带权重的循环依次来
- RandomLoadBalancer 这个是带权重的随机,阿里的默认使用
服务器线程模型
服务器采用传统netty多线程模型,一个acceptor线程专门用来接收连接,然后扔给io线程处理读消息并解码成请求对象,最后扔给业务线程池进行处理。
心跳
客户端和服务器之间会有定时心跳检测连接的存活,默认30s来一次。tcp的关闭是通过FIN包来通知对方的,如果因为网络问题,对方连FIN包都收不到,那么即使一边关闭了套接字,另一边可能还以为连接正常。所以心跳检测存活机制在长连接应用里非常普遍。如果客户端连续发了三次心跳都没有收到服务器的回复,那么就认为连接已经关闭。服务器也会有连接存活检测,如果一个客户端连接90s内没有任何消息进来,那么也认为该连接已经断开。服务器不会主动发送心跳消息。
双工通信
RPC一般是由客户端向服务器发起一个请求,然后收到服务器的应答。Bolt的RPC是双工通信,服务器也可以向客户端主动发起请求,它们共享一个TCP连接。TCP连接本身就是双工的,所以这也不算什么奇迹。只是服务器在什么业务场景需要向客户端主动发起请求,这个蚂蚁并没有进行详细说明。
客户端作为主动连接方,它要负责重连和发起心跳消息。服务器作为被动方,它不需要处理重连,如果连接断开,它就直接将连接从集合中移除就行,不需要做特殊的处理,但是它会检测心跳消息,如果在一定时间内连接通道没有任何消息到来,它就会主动关闭。
重连
客户端的重连策略是一个单独的模块,有两个地方会成为重连的入口。一个是正常连接断开触发channelInActive回调,另一个就是重连连接不能建立成功时需要进行重试。Bolt有一个单独的重连线程,所有需要重连的连接会被包装成一个任务塞进这个线程的任务队列,该线程不断地从队列里拿任务进行重连处理,如果重连失败会尝试再将任务重新包装进队列延后继续处理。默认是1s钟处理一个重连任务。
RPC连接是延迟建立的,它在第一次客户端发送RPC请求时尝试进行连接,如果连接失败,它会立即继续重连最多默认两次。如果三次尝试连接后还是没有建立成功,就向上层爆出异常。它不需要包装一个重连任务塞进ReconnectManager,因为后续客户端请求会继续触发连接。
单向消息
RPC通常是一应一答,客户端可以同步等待响应,也可以提供回调接口等待结果通知。Bolt除了提供应答模式之外,还提供了oneway单向消息,这种消息服务器收到后不用回复,客户端发送请求之后就立即返回了也不需要等待结果。
oneway消息一般用于不那么重要的日志类消息,它不能保证服务器一定能收到,所以此种业务消息应该是那种允许丢失的消息,形式上类似于UDP,它在牺牲可靠性的前提下能大幅提升消息的吞吐量。
消息追踪
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); ...}
总结
Bolt是一个成熟的比较复杂的RPC系统,这篇小文章只讲解了其中一部分,内部还有大量的实现细节有待去挖掘。
相关推荐
- NET版本众多,傻傻分不清楚
-
面对.NET众多的版本,尤其还有几个名称的情况下,相信很多初学C#的开发人员都很困惑,搞不清究竟该怎么选择。下面就列举一下.NET的主要版本及其区别:.NETFramework(传统版本,仅适用于W...
- .NET Framework 和 .NET Core 有啥区别?如何选择?
-
.NETFramework和.NETCore都是由Microsoft开发的软件框架,用于创建Windows应用程序和Web应用程序。它们的主要区别在于:支持的操作系统:.NET...
- 「分享」介绍一款倍受欢迎的.NET 开源UI库
-
概述今天要带大家了解的是一款WPF的开源控件库MahApps.Metro。MahApps.Metro是用于创建现代WPF应用程序的工具包,它许多开箱即用的好东西。目前支持的NETFramework...
- .NET 5.0正式版发布:应用可在ARM64上原生运行
-
更多:o梵蒂冈图书馆频繁遭黑客攻击oNPM包被发现窃取敏感的Discord和浏览器文件o作者:硬核老王o(本文字数:712,阅读时长大约:1分钟).NET5.0正式版发布:应用可...
- 盘点8个热门.Net开源项目
-
一、SmartFormat:轻量级文本模板库,轻松替代string.Format项目地址:https://github.com/axuno/SmartFormatSmartFormat不仅继承了s...
- .NET与Java开发:一场从框架到应用实例的深度对决
-
在软件开发这片广袤的战场上,.NET与Java两大开发平台如同两位身经百战的将军,各自率领着庞大的开发者队伍,在不同的应用场景中大放异彩。今天,我们就来一场从框架到应用实例的深度对决,看看这两大平台究...
- TouchSocket:一个功能强大且易于使用的 .NET 网络通信框架
-
项目介绍TouchSocket是一个功能强大且易于使用的.NET网络通信框架,适用于C#、VB.Net和F#等语言。它提供了多种通信模块,包括TCP、UDP、SSL、WebSocket、Mo...
- 远离报错烦恼!深入全面掌握.NET Framework
-
由于Windows系统对.NETFramework这一系统组件有着极为特殊的要求,而部分应用软件及游戏对其的依赖性也近乎达到了驱动级的水准,使用或安装不当会遭遇许多“未知”的问题,因此如何掌握.NE...
- 想自己搭建.Net Web框架,开源项目太庞大看不懂,可以看这个教程
-
大家好,我是编程乐趣。一直以来,我都在运营知识星球,这个月也开始全职专心编写教程了。当时编写教程,就是发现很多程序员工作多年了,都没自己搭建过框架,也没接触过公司的框架底层代码。这就导致一些问题,无法...
- .NET 8 + React 18 一体化开发框架!苏州码农十年匠心打磨
-
开篇前言从2014年入行至今,从WebForms到MVC,从JavaScript到React/Vue,从.NETFramework到.NETCore/8,技术栈的变迁伴随了我整个职业生涯。去年,我...
- .Net Framework详解
-
相信有不少小伙伴遇到过这种情况:安装软件时提示.NetFramework未安装导致软件无法打开,或者需要安装.NetFramework4.0以上的组件。那.NetFramework是什么呢?....
- 系统小技巧:深入全面掌握.NET Framework
-
由于Windows系统对.NETFramework这一系统组件有着极为特殊的要求,而部分应用软件及游戏对其的依赖性也近乎达到了驱动级的水准,使用或安装不当会遭遇许多“未知”的问题,因此如何掌握.NE...
- 前端架构师成长之路:如何在 Vue 的计算属性中传递参数
-
在Vue中,计算属性(computed)是从其他响应式属性派生的属性,是用于自动监听响应式属性的变化,从而动态计算返回值。计算属性(computed)通常是一个没有参数的函数。当然如果需要像调...
- Vue2 vs Vue3:核心差异与升级指南
-
Vue3自2020年发布以来,凭借其革命性的改进迅速成为开发者关注的焦点。本文将从架构设计、API模式、性能优化等多个维度深入对比Vue2和Vue3的核心差异,并提供代码示例帮助开发者...
- 突发!Vue3 投屏神器引爆程序员朋友圈
-
【AlarmLevel】重要【AlarmTitle】突发!Vue3投屏神器引爆程序员朋友圈【AlarmOverview】最近GitHub上名为vue-screen-share的仓库突...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- 若依框架 (41)
- MVC框架 (46)
- spring框架 (46)
- 框架图 (58)
- bootstrap框架 (43)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- scrapy框架 (52)
- beego框架 (42)
- java框架spring (43)
- grpc框架 (55)
- 前端框架bootstrap (42)
- orm框架有哪些 (43)
- ppt框架 (48)
- 内联框架 (52)
- winform框架 (46)
- gui框架 (44)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle v (42)
- oracle字符串长度 (48)
- oracle提交事务 (47)