什么是RPC?

RPC:远程调用,对标本地调用。至于如何远程调用,可以是HTTP,也可以基于TCP协议等。

如何设计一个RPC框架?

  • 服务的消费者
  • 服务的提供者
  • 注册中心
  • 监控运维

    Dubbo简介

    基于Java的RPC框架。实现了面向接口的代理RPC调用,配置ZK等实现服务注册和发现,并且拥有复杂均衡、容错机制等。

    基础流程

    image.png
    服务提供者Provider启动然后向注册中心注册自己能提供的服务。
    服务的消费者向注册中心订阅自己所需的服务,然后注册中心将提供者元信息通知给Consumer,之后consumer因为已经从注册中心获取提供者的地址,因此可以通过复杂均衡选择一个Provider的调用。
    之后提供方元数据变更的话,注册中心会把变更推送给服务消费者。
    服务提供者和消费者都会在内存中记录调用次数和时间,并定时的发送统计数据到监控中心。

注意:监控中心和注册中心是可选的。

Dubbo的分层架构

image.png
大的三层:业务层,RPC层,Remoting, 并且还分为API层和SPI层。而API和SPI是dubbo成功的一点,采用微内核设计+SPI扩展。方便自定义扩展。

Service层

业务层,开发的业务逻辑层

Config层

配置层,主要围绕ServiceConfig和ReferenceConfig,初始化配置信息

Proxy层

代理层,服务提供者还是消费者都会生成一个代理类,使得服务接口透明化,代理层做远程调用和返回结果。

Register层

注册层,封装了服务注册和发现。

Cluster

路由和集群容错层,负责选取具体调用的节点,处理特殊的调用要求和负责远程调用失败的容错措施

Monitor

监控层,负责监控统计调用时间和次数

Protocol

远程调用层,主要封装RPC的调用,主要负责管理Invoker,Invoker代表一个抽象封装的执行体

Exchange

信息交换层,用来封装请求的响应模型,同步转异步

Transport

网络传输层,抽象了网络传输的统一接口,这个时候用户想用Netty就用Netty,想用Mina就用Mina

Serialize

序列化层,将数据序列化为二进制流,当然也做反序列化。

SPI

JDK内置服务发现机制,使得接口和实现解耦。
定义一个接口,然后在META-INF/services目录放置一个接口同名的文本文件,文件的内容为接口的实现类。

dubbo调用过程

服务暴露过程

首先Provider启动,通过Proxy组件根据具体的协议Protocol将需要暴露出去的接口封装成invoker,invoker是Dubbo一个很核心的组件,代表一个可执行体。
然后再通过Expoter包装,这个是为了在注册中心暴露自己套的一层,然后将Expoter通过Registry注册到注册中心。这就是整体服务暴露的过程。

消费过程

消费者启动会向注册中心拉取服务提供 者元信息,然后调用流程也从Proxy开始,毕竟都需要代理才能无感知。
Proxy持有一个Invoker对象,调用invoke之后需要通过Cluster先从Directory获取所有可调用的远程服务的Invoker列表,如果配置了某些路由规则,比如某个接口只能调用某个节点的,那就再过滤一遍。

剩下的Invoker再通过LoadBalance做负载均衡选取一个,然后再经过Filter做一些统计什么的。接着就是Client传输,比方说使用Netty。

传输需要经过Codec协议构造,再序列化,最终发往对应的服务提供者。

服务提供者收到之后也会进行Codec协议处理,然后反序列化后将请求扔到线程池中处理,某个线程会根据请求找到对应的Exporter, 找到 Exporter就是找到了invoker, 但是还会有一层层Filter, 经过一层层过滤链之后最终调用实现类然后原路返回结果。

完成整个调用过程。