前言
我们有一个 HelloService 服务。实现类位于服务提供者 Provider 端,需要实现一个简单的 rpc 框架,使得服务消费者 Consumer 可以想调用本地方法一样调用 Provider 端提供的 HelloServiceImpl。
public interface HolleService {
String sayHello(String userName);
}
实现让我们再回顾一下 Dubbo 的基本工作流程:
以下实现是一种简化版的工作流程,只是大概地抽象出了 Dubbo 的工作流程。这只是一个十分十分简单的 Dubbo 实现,并没有涉及到 Dubbo 的灵魂。不过你可以通过这个实现来了解 Dubbo 远程调用的基本流程。我之后应该会在本实现的基础上进一步扩展。
Provider 端
Provider 端需要做以下步骤:
- 本地注册:将 HelloService 接口的全类限定名(服务名)映射到它的实现类 HelloServiceImpl。
- 注册服务:将 HelloService 接口的全类限定名(服务名)与本机的地址和端口发布到注册中心
- 启动 http服务器,监听调用请求
注册中心
注册中心的职责:
- 维护从 HelloService 接口的全类限定名(服务名)到 Providers 的地址和端口的映射
- 根据服务名从 Providers 中选择一个 Provider 提供服务(负载均衡器)
Consumer 端
- 根据接口全类限定名(服务名)获取代理对象
- 调用代理对象代理的方法实现远程调用
为什么需要代理对象?代理对象有什么用?
因为是远程调用,消费端并不能直接调用到服务端的服务,需要 rpc 框架为消费端提供一种远程调用方式。使用代理类包装消费端的服务请求来实现远程调用。如何实现?
消费端:
- 调用时从注册中心获取到服务名的 Provider 的调用地址
- 将调用请求参数封装为一个 Invocation 对象,其中包含接口的全类限定名(服务名),方法名,参数类型列表,参数列表。
- 向调用地址发送 http 调用请求并携带 Invocation 对象
服务端:
- 服务端的 http 服务器监听到调用请求之后取出 Invocation 对象,拿到其中的服务名(接口全类限定名)
- 根据全类限定名从本地注册列表中取出实现类,并使用反射调用方法
- 将方法执行结果返回给消费端