发布时间: 2019-01-22 19:17:51 浏览 716 评论 0
系统软件
RPC
分布式
消息系统
Redis
Java 核心技术
架构
开发框架与中间件
分布式系统与计算
java
JavaScript
实时系统
性能优化
jvm
原创
摘要: 在过去持续分享的几十期阿里 Java 面试题中, 几乎每次都会问到 Dubbo 相关问题, 比如:"如何从 0 到 1 设计一个 Dubbo 的 RPC 框架", 这个问题主要考察以下几个方面: 你对 RPC 框架的底层原理掌握程度. 考验你的整体 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+] , 本群专用于学习交流技术, 分享面试机会, 拒绝广告, 我也会在群内不定期答题, 探讨.
往期博文:
最新拼多多技术部面试题: 幻影读 + 分段锁 + 死锁 + Spring Cloud + 秒杀
阿里 P8 架构师谈: Zookeeper 的原理和架构设计, 以及应用场景
---------------end---------------------
来源: https://yq.aliyun.com/articles/688616