一、问题引入
1. 当我们写下<dubbo:service interface="MyService" ref="myServiceImpl" protocol="dubbo" registry="zookeeper"/> 时,是什么时候执行的?
2. 服务的暴露,为何暴露,何为暴露,到底暴露到哪里去了,为什么需要本地暴露?
3. 导出服务,是如何注册到注册中心的?
4. 一个导出的服务是如何跟客户端高效沟通的?
二、总体结构
1. 名词解释
Exporter和Invoker
Dubbo 服务暴露时,首先会创建一个 DubboExporter,然后再通过 netty 开启服务端口监听。 DubboExporter 的作用是缓存 Invoker,方便后续操作获取 Invoker。其中最重要的操作就是: Provider 接收到 Request 请求后,获取到对应的 Invoker,然后执行 Invoker。
URL
没有注册中心:dubbo://service-host/com.foo.FooService?version=1.0.0
有注册中心: registry://registry-host/org.apache.dubbo.registry.RegistryService?export=URL.encode("dubbo://service-host/com.foo.FooService?version=1.0.0")
2. 总体步骤
第一部分是前置工作,主要用于检查参数,组装 URL。
第二部分是导出服务,包含导出服务到本地 (JVM),和导出服务到远程两个过程。
第三部分是向注册中心注册服务,用于服务发现。
三、核心思想
1. 服务提供者暴露一个服务的详细过程
2. Invoker
3. 服务暴露时序图
四、源码解读
1. 获取invoker
准备工作做完后ProxyFactory上场,dubbo中有两种代理方式,JDK代理和Javassist代理,默认使用Javassist代理,Proxy代理类根据dubbo配置信息获取到接口信息、通过动态代理方式将接口的所有方法交给Proxy代理类进行代理,并封装进Invoker里面。
将所有需要暴露的service封装的Invoker组成一个list传给信息交换层提供给消费方进行调用。
代理模式的经典应用。
2. export
Dubbo 服务暴露时,首先会创建一个 DubboExporter,然后再通过 netty 开启服务端口监听。 DubboExporter 的作用是缓存 Invoker,方便后续操作获取 Invoker。其中最重要的操作就是: Provider 接收到 Request 请求后,获取到对应的 Invoker,然后执行 Invoker。
在服务暴露时,有两种情况:不使用注册中心:直接暴露对应协议的服务,引用服务时只能通过直连方式引用.
使用注册中心:暴露对应协议的服务后,会将服务节点注册到注册中心,引用服务时可以通过注册中心动态获取服务提供者列表,也可以通过直连方式引用
export方法其实干了两件事:
1、将Invoker export出去,然后创建 DubboExporter实例并存储在 exporterMap 里,Exporter其实就是一个存储了Invoker实例及其他各种信息的容器,用于之后获取Invoker用。
2、打开服务端口,并注册ExchangeHandler,用于后续响应客户端网络请求。
3. Registry
getRegistry() 方法根据注册中心类型(默认 Zookeeper)获取注册中心客户端,由注册中心客户端实例来进行真正的服务注册。
注册中心客户端将节点注册到注册中心,同时订阅对应的 override 数据,实时监听服务的属性变动实现动态配置功能。
模板模式的经典应用
五、拨开云雾
任何技术原理,在生活中都有参照,八卦蛇形,日月乾坤,学会独立思考,认真观察,处处皆学问。
六、看清本质
1. 服务暴露很简单,只做了两件事
1. 消费端执行DemoService service的具体方法,实际是执行代理实现类的对应方法,代理类的方法执行实际是通过invoker来执行,invoker执行的时候实际就是通过网络通信将请求发送给服务端
2、服务端接收消息进行解码,得到请求的信息,根据请求信息得到Exporter对象,根据Exporter对象可以获取Invoker对象,然后通过Invoker来执行具体的方法(这个Invoker和消费端的Invoker不是同一个实现)
2. 服务注册很简单,只做了一件事
1. 把组装的url,在zk中创建一个节点,让客户端能订阅
3. 服务暴露暴露了啥
暴露服务的时候,IP,端口,服务名称,方法名称,是要放入到注册中心的。因为最终服务的引用者是和注册中心进行交互的,获取信息
网友评论