根据配置文件请求服务端
网络
查找服务端方式:直接查找、注册中心查找
jvm
直接查找:在配置文件中直接配置服务端地址和实现接口 在没有注册中心,直连提供者的状况下(例如:<dubbo:reference url="dubbo://service-host/com.foo.FooService?version=1.0.0" />),ReferenceConfig 解析出的 URL 的格式为:dubbo://service-host/com.foo.FooService?version=1.0.0。 基于扩展点自适应机制,经过 URL 的 dubbo:// 协议头识别,直接调用 DubboProtocol 的 refer() 方法,返回提供者引用。socket
注册中心查询:经过注册中心找到服务端地址和实现接口 在有注册中心,this
一、经过注册中心发现提供者地址的状况下 (例如:<dubbo:registry address="zookeeper://10.20.153.10:2181" />),ReferenceConfig 解析出的 URL 的格式为: registry://registry-host/com.alibaba.dubbo.registry.RegistryService?refer=URL.encode("consumer://consumer-host/com.foo.FooService?version=1.0.0")。 二、基于扩展点自适应机制,经过 URL 的 registry:// 协议头识别,就会调用 RegistryProtocol 的 refer() 方法,基于 refer 参数中的条件,查询提供者 URL,如: dubbo://service-host/com.foo.FooService?version=1.0.0。 url
三、基于扩展点自适应机制,经过提供者 URL 的 dubbo:// 协议头识别,就会调用 DubboProtocol 的 refer() 方法,获得提供者引用。 而后 RegistryProtocol 将多个提供者引用,经过 Cluster 扩展点,假装成单个提供者引用返回。
3d
客户端消费过程:code
一、首先 ReferenceConfig 类的 init 方法调用 Protocol 的 refer 方法生成 Invoker 实例(如上图中的红色部分),这是服务消费的关键。cdn
二、接下来把 Invoker 转换为客户端须要的接口(如:HelloWorld)。 关于每种协议如 RMI/Dubbo/Web service 等它们在调用 refer 方法生成 Invoker 实例:blog
Dubbo 的实现 Dubbo 协议的 Invoker 转为 Exporter 发生在 DubboProtocol 类的 export 方法,它主要是打开 socket 侦听服务,并接收客户端发来的各类请求,通信细节由 Dubbo 本身实现。 接口
RMI 的实现 RMI 协议的 Invoker 转为 Exporter 发生在 RmiProtocol类的 export 方法,它经过 Spring 或 Dubbo 或 JDK 来实现 RMI 服务,通信细节这一块由 JDK 底层来实现,这就省了很多工做量。
invoker是什么?
结合服务消费和提供者的代码示例来进行说明:
服务消费者代码:
public class DemoClientAction {
private DemoService demoService;
public void setDemoService(DemoService demoService) {
this.demoService = demoService;
}
public void start() {
String hello = demoService.sayHello("world" + i);
}
}
上面代码中的 DemoService 就是上图中服务消费端的 proxy,用户代码经过这个 proxy 调用其对应的 Invoker(DubboInvoker
、 HessianRpcInvoker
、 InjvmInvoker
、 RmiInvoker
、 WebServiceInvoker
中的任何一个),而该 Invoker 实现了真正的远程服务调用。
服务提供者代码:
public class DemoServiceImpl implements DemoService {
public String sayHello(String name) throws RemoteException {
return "Hello " + name;
}
}
上面这个类会被封装成为一个 AbstractProxyInvoker 实例,并新生成一个 Exporter 实例。这样当网络通信层收到一个请求后,会找到对应的 Exporter 实例,并调用它所对应的 AbstractProxyInvoker 实例,从而真正调用了服务提供者的代码。Dubbo 里还有一些其余的 Invoker 类,但上面两种是最重要的。