实现一个超级简单的Dubbo

前言

我们有一个 HelloService 服务。实现类位于服务提供者 Provider 端,需要实现一个简单的 rpc 框架,使得服务消费者 Consumer 可以想调用本地方法一样调用 Provider 端提供的 HelloServiceImpl。

public interface HolleService {  
    String sayHello(String userName);  
}

实现让我们再回顾一下 Dubbo 的基本工作流程:

Dubbo工作流程
Dubbo工作流程

以下实现是一种简化版的工作流程,只是大概地抽象出了 Dubbo 的工作流程。这只是一个十分十分简单的 Dubbo 实现,并没有涉及到 Dubbo 的灵魂。不过你可以通过这个实现来了解 Dubbo 远程调用的基本流程。我之后应该会在本实现的基础上进一步扩展。

Provider 端

Provider 端需要做以下步骤:

  1. 本地注册:将 HelloService 接口的全类限定名(服务名)映射到它的实现类 HelloServiceImpl。
  2. 注册服务:将 HelloService 接口的全类限定名(服务名)与本机的地址和端口发布到注册中心
  3. 启动 http服务器,监听调用请求

注册中心

注册中心的职责:

  1. 维护从 HelloService 接口的全类限定名(服务名)到 Providers 的地址和端口的映射
  2. 根据服务名从 Providers 中选择一个 Provider 提供服务(负载均衡器)

Consumer 端

  1. 根据接口全类限定名(服务名)获取代理对象
  2. 调用代理对象代理的方法实现远程调用

为什么需要代理对象?代理对象有什么用?

因为是远程调用,消费端并不能直接调用到服务端的服务,需要 rpc 框架为消费端提供一种远程调用方式。使用代理类包装消费端的服务请求来实现远程调用。如何实现?

消费端:

  1. 调用时从注册中心获取到服务名的 Provider 的调用地址
  2. 将调用请求参数封装为一个 Invocation 对象,其中包含接口的全类限定名(服务名),方法名,参数类型列表,参数列表。
  3. 向调用地址发送 http 调用请求并携带 Invocation 对象

服务端:

  1. 服务端的 http 服务器监听到调用请求之后取出 Invocation 对象,拿到其中的服务名(接口全类限定名)
  2. 根据全类限定名从本地注册列表中取出实现类,并使用反射调用方法
  3. 将方法执行结果返回给消费端

仓库地址

Mvbbb/simple-dubbo (github.com)