高并发架构系列:如何从0到1设计一个类Dubbo的RPC框架
在过去持续分享的几十期阿里Java面试题中,几乎每次都会问到Dubbo相关问题,比如:“如何从0到1设计一个Dubbo的RPC框架”,这个问题主要考察以下几个方面:
你对RPC框架的底层原理掌握程度。
考验你的整体RPC框架系统设计能力。
具体,mike来为大家详解。
RPC和RPC框架
1.RPC(Remote Procedure Call)
即远程过程调用, 主要解决远程通信间的问题,不需要了解底层网络的通信机制。
2.RPC框架
- RPC框架负责屏蔽底层的传输方式(TCP或者UDP)、序列化方式、以及通信细节。
- 实际使用中,并不需要关心底层通信细节和调用过程,让业务端专注于业务代码的实现。
- 国内大家熟知的PRC框架,阿里的HSF和Dubbo(开源)
Dubbo的发展由来
1. 业务规模小
比如早期一个应用Java War包,将所有功能都打包,部署在一个单机服务器,调用接口也比较方便,不涉及到任何分布式场景。
2.业务规模变大
随着业务的快速发展,业务越来越多、子系统也越来越多时。比如:淘宝的交易系统、商品系统、用户系统、评价系统...上百个系统的出现。
系统变得越来越复杂,业务代码依然耦合在一起。比如最早期的淘宝denali工程,包含所有业务系统的代码,就仅打包部署都需要很长的时间。
并且,随着每个业务线的快速发展,业务代码耦合在一起,上线后出现问题急需要回滚代码,拉分支、大量的代码merge工作,这个过程极其痛苦。
这个时候,你会发现技术已经成了业务的瓶颈,急需把业务单独抽离出来,各自单独部署。
3.Dubbo和HSF的出现
应用系统一旦涉及到拆分部署,问题就来了,急需一种高效的应用程序间的通讯手段来完成这种需求,这就会涉及到分布式远程调用。
于是,淘宝就把denali按照业务为单位拆分成了类似这样的系统:UM(UserManger)、SM(ShopManager)..等等几十个工程代码。
再按照业务为单位,把所有调用相关的接口以业务为单元进行拆分;- UIC(用户中心服务)、SIC(店铺中心服务)...等等以业务为单位集群部署,按照业务提供服务。
所以,RPC的框架来了,阿里内部使用HSF,以及开源的RPC框架:Dubbo。
RPC框架的核心设计
前面mike提到了RPC的核心目标:主要是解决分布式系统中服务之间的调用问题。
其实,走到这一步涉及的知识体系非常的多:要求对通信、远程调用、消息机制等有深入的理解和掌握,要求的都是从理论、硬件级、操作系统级以及所采用的语言的实现都有清楚的理解。
1.RPC框架三个核心角色
1)服务提供者(Server)
对外提供后台服务,将自己的服务信息,注册到注册中心
2)注册中心(Registry)
用于服务端注册远程服务以及客户端发现服务。
目前主要的注册中心可以借由 zookeeper,eureka,consul,etcd 等开源框架实现。
比如:阿里的Dubbo就是采用zookeeper实现注册中心。
3)服务消费者(Client)
从注册中心获取远程服务的注册信息,然后进行远程过程调用。
2.RPC远程调用过程
1)服务调用方(client)调用以本地调用方式调用服务;
2)client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;在Java里就是序列化的过程
3)client stub找到服务地址,并将消息通过网络发送到服务端;
4)server stub收到消息后进行解码,在Java里就是反序列化的过程;
5)server stub根据解码结果调用本地的服务;
6)本地服务执行处理逻辑;
7)本地服务将结果返回给server stub;
8)server stub将返回结果打包成消息,Java里的序列化;
9)server stub将打包后的消息通过网络并发送至消费方
10)client stub接收到消息,并进行解码, Java里的反序列化;
11)服务调用方(client)得到最终结果。
RPC框架的目标就是要2~10这些步骤都封装起来。
RPC框架涉及技术
1.建立通信
首先,要解决通讯的问题,主要是通过在客户端和服务器之间建立TCP连接,远程过程调用的所有交换的数据都在这个连接里传输。
2.服务寻址
1)服务注册
首先需要把服务注册到服务中心。其实就是在注册中心进行一个登记,注册中心存储了该服务的IP、端口、调用方式(协议、序列化方式)等。在zookeeper中,进行服务注册,实际上就是在zookeeper中创建了一个znode节点,该节点存储了上面所说的服务信息。
2)服务发现
服务消费者在第一次调用服务时,会通过注册中心找到相应的服务的IP地址列表,并缓存到本地,以供后续使用。当消费者调用服务时,不会再去请求注册中心,而是直接通过负载均衡算法从IP列表中取一个服务提供者的服务器调用服务。
3)注册服务
可靠的寻址方式(主要是提供服务的发现)是RPC的实现基石,比如可以zookeeper来实现注册服务等等。
- 服务提供者启动后主动向服务(注册)中心注册机器ip、端口以及提供的服务列表。
- 服务消费者启动时向服务(注册)中心获取服务提供方地址列表,可实现软负载均衡和Failover。
- 提供者需要定时向注册中心发送心跳,一段时间未收到来自提供者的心跳后,认为提供者已经停止服务,从注册中心上摘取掉对应的服务等等。
3.网络传输
数据传输采用什么协议,数据该如何序列化和反序列化。
4.NIO通信
当前很多RPC框架都直接基于netty这一IO通信框架,比如阿里巴巴的HSF、dubbo,Hadoop Avro,推荐使用Netty 作为底层通信框架。
5.服务调用
比如:B机器进行本地调用(通过代理Proxy)之后得到了返回值,此时还需要再把返回值发送回A机器,同样也需要经过序列化操作,然后再经过网络传输将二进制数据发送回A机器,而当A机器接收到这些返回值之后,则再次进行反序列化操作。
总之,要实现一个RPC不算难,难的是实现一个高性能高可靠的RPC框架,后续将结合Dubbo的实现一起再探讨。
以上就是RPC的介绍,更多Redis、Spring Cloud、MySQL数据库分库分表等高并发架构设计,具体请参考高并发架构系列专题:
觉得不错请点赞支持,欢迎留言或进我的个人群179961551领取【架构资料专题目合集90期】、【BATJTMD大厂JAVA面试真题1000+】,本群专用于学习交流技术、分享面试机会,拒绝广告,我也会在群内不定期答题、探讨。
高并发架构系列:如何从0到1设计一个类Dubbo的RPC框架的更多相关文章
- 如何从0到1设计一个类Dubbo的RPC框架
之前分享了如何从0到1设计一个MQ消息队列,今天谈谈"如何从0到1设计一个Dubbo的RPC框架",重点考验: 你对RPC框架的底层原理掌握程度. 以及考验你的整体RPC框架系统设 ...
- 面试系列 30 如何自己设计一个类似dubbo的rpc框架
其实一般问到你这问题,你起码不能认怂,因为既然咱们这个课程是短期的面试突击训练课程,那我不可能给你深入讲解什么kafka源码剖析,dubbo源码剖析,何况我就算讲了,你要真的消化理解和吸收,起码个把月 ...
- 高并发架构系列:Redis并发竞争key的解决方案详解
https://blog.csdn.net/ChenRui_yz/article/details/85096418 https://blog.csdn.net/ChenRui_yz/article/l ...
- 高并发架构系列:MQ消息队列的12点核心原理总结
消息队列已经逐渐成为分布式应用场景.内部通信.以及秒杀等高并发业务场景的核心手段,它具有低耦合.可靠投递.广播.流量控制.最终一致性 等一系列功能. 无论是 RabbitMQ.RocketMQ.Act ...
- 高并发架构系列:Redis为什么是单线程、及高并发快的3大原因详解
Redis的高并发和快速原因 1.redis是基于内存的,内存的读写速度非常快: 2.redis是单线程的,省去了很多上下文切换线程的时间: 3.redis使用多路复用技术,可以处理并发的连接.非阻塞 ...
- 高并发架构系列:Redis缓存和MySQL数据一致性方案详解
一.需求起因 在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节.所以,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问MySQL等数据库. 这个业务场景, ...
- 朱晔的互联网架构实践心得S2E6:浅谈高并发架构设计的16招
朱晔的互联网架构实践心得S2E6:浅谈高并发架构设计的16招 概览 标题中的高并发架构设计是指设计一套比较合适的架构来应对请求.并发量很大的系统,使系统的稳定性.响应时间符合预期并且能在极端的情况下自 ...
- 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存
原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...
- [ 高并发]Java高并发编程系列第二篇--线程同步
高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...
随机推荐
- YARN的架构及原理
1. YARN产生背景 MapReduce本身存在着一些问题: 1)JobTracker单点故障问题:如果Hadoop集群的JobTracker挂掉,则整个分布式集群都不能使用了. 2)JobTrac ...
- vs2017通过snippet代码片断进行标准化注释
我们在进行团队开发时,类的注释已经可以做到自定义了,详细看上篇文章<vs2017通过模块文件添加自定义注释>,而对于方法的注释,我们也需要完善一下,这里我们用到了“代码片断”插件,VS里有 ...
- mybatis批量插入插入数据、批量条件查询
ps:参考文章连接:https://www.cnblogs.com/admol/articles/4248159.html 关于个人的使用经验:先把数据放到bean中,多个的话就全放入list集合,如 ...
- JavaSE之Java基础(4)
16.String.StringBuilder和StringBuffer的区别 String类是final的,不可变,StringBuilder和StringBuffer可变: 大部分情况下的执行效率 ...
- enable orgmode latex preview to support retina on mac
Table of Contents 1. enable orgmode latex preview to support retina on mac 1.1. get the proper versi ...
- SublimeText相关配置
安转插件:案例格式化HTML代码,需要安装插件,具体安装步骤如下: 1.打开菜单->首选项->插件控制,输入 install package 2.等待程序进入插件管理功能,再输入插件名称: ...
- javascript动态修改对象的属性名
在做东钿业务系统的时候,经常碰到写很多重复的ajax对接,于是就想封装一个方法,但是接收data的字段名不一样,所以就需要用到动态对象属性名这个写法了.其实很简单.直接看一下代码吧.
- VC使用编译时间作为版本号
常用方法分两步:1. 得到编译时间:2. 设置基准时间,以编译时间距基准时间的总天数的2倍作为版本号,适当情况还可加上初值: 其中第一步实现有两种方法: 1. 直接使用系统宏:CString OcxT ...
- 【extjs6学习笔记】1.11 初始: config
Ext JS有一个名为config的功能. 该配置允许您使用默认值声明公共属性,这些属性将被其他类成员完全封装. 通过config声明的属性将自动获取get()和set()方法,如果类没有定义这些方法 ...
- 逐步解读String类(一)
一句题外话 面试刚入行的Java新手,侧重基础知识:面试有多年工作经验的老鸟,多侧重对具体问题的解决策略. 从一类面试题说起 考察刚入行菜鸟对基础知识的掌握程度,面试官提出关于String类的内容挺常 ...