上次我们简单介绍了一下Dubbo,知道了Dubbo是一个分布式服务框架,将复杂的调用关系简单的管理起来,不管是从设计思路,还是性能提升上,它都是一个优秀的产品。如果我们不知道它的工作原理,那么我就相当于没接触过Dubbo,而且我们可以发现它的原理会更有趣。既然是这样,那我们就赶紧开始吧。
一、架构图解
1、架构图
2、角色
Provider: 暴露服务的服务提供方。
Consumer: 调用远程服务的服务消费方。
Registry: 服务注册与发现的注册中心。
Monitor: 统计服务的调用次调和调用时间的监控中心。
Container: 服务运行容器。
3、调用关系
0 服务容器负责启动,加载,运行服务提供者。
1 服务提供者在启动时,向注册中心注册自己提供的服务。
2 服务消费者在启动时,向注册中心订阅自己所需的服务。
3 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
二、重点解析
这里我们可能最不明白的还是生产这和消费者。那么服务的提供方就是生产者,服务的调用方就是消费者。
当别人需要调用我们的服务(方法)的时候,我们在服务方的提供方Provider写一个来提供该服务;当我们需要调用其他服务时,需要在Consumer来调用一个服务。
1、服务提供者暴露一个服务的详细过程
具体服务到Invoker的转化
首先ServiceConfig类拿到对外提供服务的实际类ref(如:HelloWorldImpl),然后通过ProxyFactory类的getInvoker方法使用ref生成一个AbstractProxyInvoker实例.
Invoker转换到Exporter
Dubbo的实现:Dubbo协议的Invoker转为Exporter发生在DubboProtocol类的export方法,它主要是打开socket侦听服务,并接收客户端发来的各种请求,通讯细节由Dubbo自己实现。
RMI的实现:RMI协议的Invoker转为Exporter发生在RmiProtocol类的export方法,它通过Spring或Dubbo或JDK来实现RMI服务,通讯细节这一块由JDK底层来实现,这就省了不少工作量。
2、服务消费者消费一个服务的详细过程
首先ReferenceConfig类的init方法调用Protocol的refer方法生成Invoker实例(如上图中的红色部分),这是服务消费的关键。接下来把Invoker转换为客户端需要的接口(如:HelloWorld)。
3、详解Invoker
由于Invoker是Dubbo领域模型中非常重要的一个概念,很多设计思路都是向它靠拢。这就使得Invoker渗透在整个实现代码里,对于刚开始接触Dubbo的人,确实容易给搞混了。
上图中的具体服务类会被封装成为一个AbstractProxyInvoker实例,并新生成一个Exporter实例。
这样当我们调用服务消费时,用户代码通过上图中服务消费端的proxy调用其对应的Invoker(DubboInvoker、 HessianRpcInvoker、 InjvmInvoker、 RmiInvoker、 WebServiceInvoker中的任何一个),而该Invoker通过网络通讯层的传输,会找到对应的Exporter实例,并调用它所对应的AbstractProxyInvoker实例,从而真正调用了服务提供者的代码,实现了远程服务调用。
总结:
通过此次学习,我们知道了Dubbo架构的工作原理,知道了服务如何提供并消费,但是什么是注册,为什么要注册我们还不太明白,后边我们在介绍zookeeper的时候会一一讲解。