序
修改dubbo-demo子项目的dubbo-demo-provider模块的main/resources/dubbo-demo-provider.xml中注册中心的配置:
1 | <!-- 使用multicast广播注册中心暴露服务地址 --> |
同时修改dubbo-demo子项目的dubbo-demo-provider模块的test/resources/dubbo.properties文件中:
1 | #dubbo.registry.address=multicast://224.5.6.7:1234 |
需要外部下载启动zookeeper组件。
然后启动dubbo-demo-provider/test/java下的DemoProvider观察服务启动日志:
从Provider启动日志可以看到,主要做了6个发布动作:
1 | 1.暴露本地服务 |
暴露的服务,其实就是dubbo-demo-provider.xml中配置的service:
1 | <!-- 和本地bean一样实现服务 --> |
dubbo:service是在dubbo-config-spring下resources/META-INF下的dubbo.xsd约束schema文件中定义的。
而处理Handler在dubbo-config-spring下的schema包下的DubboNamespaceHandler.java中处理:
1 | public class DubboNamespaceHandler extends NamespaceHandlerSupport { |
可以看到,service标签对应的Bean为ServiceBean。看看ServiceBean类继承关系:
1 | public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware |
这里ServiceBean继承自ServiceConfig,并且实现了Spring框架的ApplicationListener接口。
1 | public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { |
所以在Spring框架启动时,会去回调执行ServiceBean的onApplicationEvent(e)方法。
1 | public void onApplicationEvent(ApplicationEvent event) { |
执行调用分析如下:
1 | ServiceBean.onApplicationEvent |
这里分为本地暴露和远程暴露。那么暴露本地服务和暴露远程服务的区别是什么?
1.暴露本地服务:指暴露在用一个JVM里面,不用通过调用zk来进行远程通信。例如:在同一个服务,自己调用自己的接口,就没必要进行网络IP连接来通信。
2.暴露远程服务:指暴露给远程客户端的IP和端口号,通过网络来实现通信。
本地暴露
1 | //配置不是remote的情况下做本地暴露 (配置为remote,则表示只暴露远程服务) |
(1)这里的proxyFactory是什么?
1 | "javassist") ( |
可以看出proxyFactory是一个代理,作用是获取一个接口的代理类,例如获取一个远程接口的代理。
getInvoker:针对server端,将服务对象,如DemoServiceImpl包装成一个Invoker对象。
getProxy:针对client端,创建接口的代理对象,例如DemoService的接口。
(2)上面还出现了Wrapper,这个又是做什么的?
它类似spring的BeanWrapper,它就是包装了一个接口或一个类,可以通过wrapper对实例对象进行赋值、取值以及指定方法的调用。
(3)Invoker
Invoker:它是一个可执行的对象,能够根据方法的名称、参数得到相应的执行结果。
1 | 它里面有一个很重要的方法 Result invoke(Invocation invocation), |
远程暴露
远程暴露过程中使用Netty进行通信。接着前面分析:
1 | //如果配置不是local则暴露为远程服务.(配置为local,则表示只暴露本地服务) |
①Protocol
1.export:暴露远程服务(用于服务端),就是将proxyFactory.getInvoker创建的代理类 invoker对象,通过协议暴露给外部。
2.refer:引用远程服务(用于客户端), 通过proxyFactory.getProxy来创建远程的动态代理类,例如DemoService的远程动态接口。
②exporter:维护invoker的生命周期。
③exchanger:信息交换层,封装请求响应模式,同步转异步。
④transporter:网络传输层,用来抽象netty和mina的统一接口。
接着前面Netty分析之后,来分析Dubbo中的Zookeeper使用机制。
关注如下三个问题:
①dubbo如何连接zookeeper?
1 | -->getRegistry(originInvoker)//连接zookeeper |
②dubbo如何创建zookeeper节点?
1 | -->registry.register(registedProviderUrl)//创建节点 |
zk持久化节点和临时节点有什么区别?
持久化节点:一旦被创建,除非主动删除掉,否则就一直存储在zk里面。
临时节点:与客户端会话绑定,一旦客户端会话失效,这个客户端端所创建的所有临时节点都会被删除。Dubbo对注册的服务使用临时节点,保证服务断掉时节点自动被移除,以免订阅者一直订阅。比如服务端已经挂了,但是在Zk中仍然存在,那么客户端还是会去请求和监听,那么会一直失败。
③dubbo如何订阅zookeeper信息?
1 | -->registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);//订阅ZK |
最后再跟一下notify的处理流程:
1 | -->notify(url, listener, urls) |
整个服务发布流程如下: