如何从0到1设计一个类Dubbo的RPC框架

如何从0到1设计一个类Dubbo的RPC框架

之前分享了如何从0到1设计一个MQ消息队列,今天谈谈”如何从0到1设计一个Dubbo的RPC框架”,重点考验:

  • 你对RPC框架的底层原理掌握程度。
  • 以及考验你的整体RPC框架系统设计能力。

RPC和RPC框架

1.RPC(Remote Procedure Call)

即远程过程调用, 主要解决远程通信间的问题,不需要了解底层网络的通信机制。

2.RPC框架

RPC框架负责屏蔽底层的传输方式(TCP或者UDP)、序列化方式、以及通信细节。

实际使用中,并不需要关心底层通信细节和调用过程,让业务端专注于业务代码的实现。

国内大家熟知的PRC框架,阿里的HSF和 Dubbo(开源)

Dubbo的发展由来

1. 业务规模小

比如早期一个应用Java War包,将所有功能都打包,部署在一个单机服务器,调用接口也比较方便,不涉及到任何分布式场景。

2.业务规模变大

随着业务的快速发展,业务越来越多、子系统也越来越多时。比如:淘宝的交易系统、商品系统、用户系统、评价系统…上百个系统的出现。

如何从0到1设计一个类Dubbo的RPC框架

系统变得越来越复杂,业务代码依然耦合在一起。比如最早期的淘宝denali工程,包含所有业务系统的代码,就仅打包部署都需要很长的时间。

并且,随着每个业务线的快速发展,业务代码耦合在一起,上线后出现问题急需要回滚代码,拉分支、大量的代码merge工作,这个过程极其痛苦。

这个时候,你会发现技术已经成了业务的瓶颈,急需把业务单独抽离出来,各自单独部署。

3.Dubbo和HSF的出现

应用系统一旦涉及到拆分部署,问题就来了,急需一种高效的应用程序间的通讯手段来完成这种需求,这就会涉及到 分布式远程调用

于是,淘宝就把denali按照业务为单位拆分成了类似这样的系统:UM(UserManger)、SM(ShopManager)..等等几十个工程代码。

再按照业务为单位,把所有调用相关的接口以业务为单元进行拆分:UIC(用户中心服务)、SIC(店铺中心服务)…等等以业务为单位集群部署,按照业务提供服务。

所以,RPC的框架来了,阿里内部使用HSF,以及开源的RPC 框架:Dubbo。

RPC框架的核心设计

前面mikechen提到了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 作为底层通信框架。

  1. 服务调用

比如:B机器进行本地调用(通过代理Proxy)之后得到了返回值,此时还需要再把返回值发送回A机器,同样也需要经过序列化操作,然后再经过网络传输将二进制数据发送回A机器,而当A机器接收到这些返回值之后,则再次进行反序列化操作

总之,要实现一个RPC不算难,难的是实现一个高性能高可靠的RPC框架,如果还想更加深入了解请查看Dubbo源码剖析,看看Dubbo是如何来解决这些难题。

关于作者:mikechen,十余年BAT架构经验,资深技术专家,曾任职阿里、淘宝、百度。

关注作者公众号:回复【 架构】,即可查看mikechen互联网架构 原创的300期+BAT架构技术系列文章与1000+大厂面试题答案合集

如何从0到1设计一个类Dubbo的RPC框架

Original: https://www.cnblogs.com/mikechenshare/p/15903087.html
Author: mikechen的互联网架构
Title: 如何从0到1设计一个类Dubbo的RPC框架

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/617072/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • java进程占用CPU或者内存高问题排查

    排查步骤: 1. 使用top命令查看系统资源的使用情况, 命令: top 如图:排行前面的就是占用资源最多的 2.定位线程问题 方法一: top -Hp 查看线程 :使用命令 to…

    Java 2023年6月8日
    097
  • java服务器端Mock服务接口模拟实践入门

    Mock服务的使用目的在于前端测试、APP开发、前端测试人员在服务还没完备时模拟接口。 本篇里实现实时动态mock的完整代码: https://gitee.com/475660/d…

    Java 2023年5月29日
    056
  • 线程的生命周期

    线程的生命周期​ 线程具有生命周期,其中包含 5种状态(出生状态,就绪状态,运行状态、暂停状态、死亡状态)。 出生状态就是线程被创建时的状态:当线程对象调用 start()方法 后…

    Java 2023年6月9日
    091
  • java中线程的几种实现方式

    继承Thread类来实现 由于在java中采用单继承的模式,因此继承Thread类有一个明显的缺点就是占用了唯一的extends,是的我们无法在继承其它的类,因此一般不会采用这种方…

    Java 2023年6月6日
    089
  • String与StringBuilder相互转换以及获取字符串中第一个中文汉字

    String与StringBuilder相互转换 1. StringBuilder转为String StringBuilder sb = new StringBuilder(); …

    Java 2023年6月14日
    074
  • Java 8 Collectors.collectingAndThen()

    JDK源码 java.util.stream.Collectors#collectingAndThen方法的作用是将Collector的结果在执行一个额外的finisher转换操作…

    Java 2023年5月29日
    086
  • Windows开机自启动运行Java的jar包

    C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp 在该目录下新建web-start.bat文件,命名可自定义…

    Java 2023年5月29日
    074
  • rabbitmq web管理

    celery突然连接不上rabbitmq server,结果找半天发现是rabbitmq卡的不行。。。 rabbitmq 设置web管理,添加用户 rabbitmqctl list…

    Java 2023年5月30日
    078
  • SpringCloud-Ribbon

    1. Ribbon简介 Ribbon是一个基于HTTP和TCP的客户端负载均衡器,当使用Ribbon对服务进行访问的时候,他会扩展Eureka客户端的服务发现功能,实现从Eurek…

    Java 2023年6月7日
    082
  • 服务路由

    前言 本文基于Dubbo2.6.x版本,中文注释版源码已上传github:xiaoguyu/dubbo 今天,来聊点短的,服务路由 Router,本文讲的是路由的调用路径,不讲路由…

    Java 2023年6月16日
    0106
  • Eclipse 教程如C,C++,PHP,和 Ruby

    Eclipse教程 C C++ PHP Ruby Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。 Eclipse 是 Java 的集成开发环境(IDE),当…

    Java 2023年6月9日
    086
  • 多线程那点事—Parallel.for

    先看段代码: 1 for (int i = 0; i < 10; i++) 2 { 3 Task.Factory.StartNew(()=>Console.WriteL…

    Java 2023年6月9日
    089
  • RocketMQ

    应用场景 主要作用解耦、滑峰填谷 异构系统的整合,这个问题比较容易理解,在原阿里SOA ESB比较火的年代,很多异构系统需要进行互联互通。 应用和应用之间的松耦合,这个在阿里巴巴内…

    Java 2023年5月30日
    079
  • 记录一次 java.lang.IncompatibleClassChangeError: Implementing class

    原因:部署的项目中存在jar重复加载导致的 解决:移除掉没必要的重复类的包/类 比如:下面这句执行报标题的错 csharp;gutter:true;final SM2 sm2 = …

    Java 2023年5月29日
    082
  • RocketMQ基本原理

    基础概念 RocketMQ主要由Producer、Broker、Consumer三部分组成,其中Producer负责生产消息,Consumer负责消费消息,Broker负责存储消息…

    Java 2023年6月6日
    078
  • EasyExcel的基本使用

    官方网址:https://www.yuque.com/easyexcel/doc/easyexcel 应用场景 数据导入:减少录入工作量 数据导出:统计信息归档 数据传输:异构系统…

    Java 2023年6月13日
    095
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球