如何实现一个分布式 RPC 框架
远程过程调用(Remote Procedure Call,RPC)是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。RPC的主要目标是让构建分布式应用更加容易,在提供强大的远程调用能力的同时不损失本地调用的语义的简洁性。
趁实习前的这段业余时间,我实现了一个轻量级的分布式RPC框架,名字叫做 buddha,代码量不大,但是麻雀虽小却五脏俱全。本篇文章将一步步阐明buddha的设计、框架组件的拆解以及需要考虑的因素。
序列化与反序列化
在网络中,所有的数据都将会被转化为字节进行传送,所以在代码层面上,一个RPC框架需要实现特定格式的数据与字节数组之间的相互转化。像Java已经提供了默认的序列化方式,但是如果是在高并发的场景下,使用Java原生的序列化方式可能会遇到性能瓶颈。于是,出现了许多开源的、高效的序列化框架:如Kryo、fastjson和Protobuf等。buddha目前支持Kryo和fastjson两种序列化框架。
TCP拆包、粘包
由于TCP只关心字节流,并不知晓上层的数据格式。如果客户端应用层一次要发送的数据过大时,TCP会将该数据进行分解传送,因此在服务端需要进行粘包处理(由TCP来保证数据的有序性);如果客户端一次要发送的数据量很小时,TCP并不会马上把数据发送出去,而是将其存储在缓冲区,当达到某个阈值的时候再发送出去,因此在服务端需要进行拆包的工作。
通过以上分析,我们了解了TCP粘包或者拆包的原因,解决这个问题的关键在于向数据包添加边界信息,常用的方法有如下三个。
- 发送端给每个数据包添加包首部,首部中至少包含数据包的长度,这样在接收端接收到数据时,通过读取首部的长度信息得到该数据包有效数据的长度。
- 发送端将每个数据包封装为固定长度(多余用0填充),这样接收端在接收到数据后根据约定好的固定长度读取每个数据包的数据。
- 使用特殊符号将每个数据包区分开来,接收端也是通过该特殊符号的划分数据包的边界。
buddha采用第一种方式来解决TCP拆包、粘包的问题。
BIO与NIO
BIO往往用于经典的每连接每线程模型,之所以使用多线程,是因为像accept()、read()和write()等函数都是同步阻塞的,这意味着当应用为单线程且进行IO操作时,如果线程阻塞那么该应用必然会进入挂死状态,但是实际上此时CPU是处于空闲状态的。开启多线程,就可以让CPU去为更多的线程服务,提高CPU的利用率。但是在活跃线程数较多的情况下,采用多线程模型回带来如下几个问题。
- 线程的创建和销毁代价颇高,在Linux操作系统中,线程本质上就是一个进程,创建和销毁线程属于重量级的操作。
- 在JVM中,每个线程会占用固定大小的栈空间,而JVM的内存空间是有限的,因此如果线程数量过多那么线程本身就会占据过多的资源。
- 线程的切换成本较高,每次线程切换需要涉及上下文的保存、恢复以及用户态和内核态的切换。如果线程数过多,那么会有较大比例的CPU时间花费在线程切换上。
使用线程池的方式解决前两个问题,但是线程切换带来的开销还是存在。所以在高并发的场景下,传统的BIO是无能为力的。而NIO的重要特点是:读、写、注册和接收函数,在等待就绪阶段都是非阻塞的,可以立即返回,这就允许我们不使用多线程充分利用CPU。如果一个连接不能读写,可以把这个事件记录下来,然后切换到别的就绪的连接进行数据读写。在buddha中,Netty被用来编写结构更加清晰的NIO程序。
服务注册与发现
在实际应用中,RPC服务的提供者往往需要使用集群来保证服务的稳定性与可靠性。因此需要实现一个服务注册中心,服务提供者将当前可用的服务地址信息注册至注册中心,而客户端在进行远程调用时,先通过服务注册中心获取当前可用的服务列表,然后获取具体的服务提供者的地址信息(该阶段可以进行负载均衡),根据地址信息向服务提供者发起调用。客户端可以缓存可用服务列表,当注册中心的服务列表发生变更时需要通知客户端。同时,当服务提供者变为不可用状态时也需要通知注册中心服务不可用。buddha使用ZooKeeper实现服务注册与发现功能。
代码实现
buddha是我学习验证RPC过程中诞生的一个轻量级分布式RPC框架,代码放在了 GitHub。
参考
- RPC 的概念模型与实现解析
- NettyRpc
如何实现一个分布式 RPC 框架相关推荐
- 自己动手从0开始实现一个分布式RPC框架
简介: 如果一个程序员能清楚的了解RPC框架所具备的要素,掌握RPC框架中涉及的服务注册发现.负载均衡.序列化协议.RPC通信协议.Socket通信.异步调用.熔断降级等技术,可以全方位的提升基本素质 ...
- 一个轻量级分布式RPC框架--NettyRpc
1.背景 最近在搜索Netty和Zookeeper方面的文章时,看到了这篇文章<轻量级分布式 RPC 框架>,作者用Zookeeper.Netty和Spring写了一个轻量级的分布式RPC ...
- 轻量级分布式 RPC 框架
RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样. RPC 可基于 HTTP 或 TCP 协议,Web Servi ...
- dubbo-快速入门-分布式RPC框架Apache Dubbo
文章目录 分布式RPC框架Apache Dubbo 1. 软件架构的演进过程 1.1 单体架构 1.2 垂直架构 1.3 SOA架构 1.4 微服务架构 2. Apache Dubbo概述 2.1 D ...
- 还发愁项目经验吗?基于Netty实现分布式RPC框架[附完整代码]
写给大家的话 最近我收到很多读者的来信,对如何学习分布式.如何进行项目实践和提高编程能力,存在很多疑问. 分布式那么难,怎么学?为什么看了那么多书还是掌握不了? 开源的框架比如Dubbo代码太多了,完 ...
- 基于zeromq的高性能分布式RPC框架Zerorpc 性能测试
Zeromq 是基于zeromq.gevent和 msgpack开发的分布式RPC框架zerorpc-python.这个框架简单.易用. 1. 安装zeromq 1 2 3 4 5 6 yum -y ...
- 分布式RPC框架Apache Dubbo
分布式RPC框架Apache Dubbo 1. 软件架构的演进过程 软件架构的发展经历了由单体架构.垂直架构.SOA架构到微服务架构的演进过程,下面我们分别了解一下这几个架构. 1.1 单体架构 1. ...
- 分布式RPC框架Dubbo详解
目录 1.架构演进 1.1 单体架构 1.2 垂直架构 1.3 分布式架构 1.4 SOA架构 1.5 微服务架构 2.RPC框架 2.1 RPC基本概念介绍 2.1.1 RPC协议 2.1.2 R ...
- 轻量级分布式 RPC 框架DIY(转)
http://www.csdn123.com/html/topnews201408/67/12167.htm RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点 ...
最新文章
- 吃货都是怎么给自己找理由的? | 今日最佳
- 微信支付 商户Key 支付Key API密钥 的获取
- 再见 Spring Task,这个定时任务框架真香!
- 售价17999元起,华为Mate X2发布;程序员10万“买”了个北京户口;赏金猎人获苹果5000美元奖励 | 极客头条...
- 西门子大中华区总裁兼CEO赫尔曼:智能自主制造将重塑工业格局!
- 技术圈几个牛逼的公号推荐给大家
- php 获取access token,百度应用获取Access Token
- bootstraptable 一条数据跨行_据说它是唐山市拥有奶茶店最多的一条街,你一定也逛过!...
- 直播源批量生成小工具.c
- 车企建设CDP可能会遇到的坑和挑战,从CRM、SCRM到CDP
- Edraw Max 9.4中文版激活教程
- tomcat 环境迁移至weblogic 下载文件失败
- Matlab实现均值滤波与FPGA进行对比,并采用modelsim波形仿真
- 对于接口得容错性测试
- 提取Blast2go blast结果中的一部分
- 【转】Photoshop 用户名.组织或序列号丢失或无效.应用程序无法继续.
- S5PV210 对电源、地,DQ, DQM, DQS 信号的布线向导
- IDEA Eval Reset 使用方法
- 统计一组名字中每个姓出现的次数
- SonicWALL防火墙恢复出厂设置Reset
热门文章
- myqltransactionRollbackexception deadlock found when trying to get lock
- 算法与数据结构(冒泡排序)
- Spring-AOP @AspectJ进阶之绑定类注解对象
- Oracle优化07-分析及动态采样-动态采样
- ORACLE-WITH 子句详解
- JAVA如何在画板加分数_自学了java一段时间,做了个最低配的画板
- 学习笔记Kafka(三)—— Kafka安装配置(2)—— Kafka单代理及常用操作
- linux内核引入模块机制好处,linux内核模块的版本检查机制
- aboboo 上一句 快捷键_Word快捷键大全
- Halcon初学者知识 【11】自定义算子和应用实例