dubbo架构原理

角色

registry
consumer
provider
monitor

  1. 启动流程

启动流程

内核

一. SPI
代码

ExtensionLoader.getExtensionLoader(Log.class).getDefaultExtension();

  • getExtensionLoader

getExtensionLoader(Log.class) 往静态map中添加 key=Log.class,value=ExtensionLoader(Class type)

  • getDefaultExtension() 获取默认的Log实例
  > getExtension(String name)  根据默认的key获取是咧
	 > createExtension(name)  如果实例不存在则创建实例
		 > getExtensionClasses().get(name)  从cachedClasses即所有的扩展Class中拿到Class
		    > loadExtensionClasses()  如果cachedClasses是空的则加载所有的扩展Class,并且获取默认key值
		      > loadFile(extensionClasses, FEI_CHAO_DIRECTORY); 从文件中加载素有的扩展类Class
	 > clazz.newInstance()  创建实例
  • loadFile
    cachedAdaptiveClass //类有adaptive注解就赋值,
    cachedWrapperClasses//类无adapteive注解并且构造函数还目标接口(type)类型,例如ProtocolFilterWrapper类,com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper和com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper,这两个类不含有@Adaptive注解且具有含有Protocol的单参构造器,这里使用了装饰器模式。
    cachedActives//类含Activate注解
    cachedNames//剩下的类就存储在这里
    二. SPI机制的adpative原理

  注解在类上:代表人工实现编码,即实现了一个装饰类,例如ExtensionFactory
  注解在方法上:代表自动生成和编译一个动态的adpative类,例如Protocol$Adaptive
  动态类模板,用javassist生成的动态代理类,代理类模板如下:
package <扩展点接口所在包>;
public class <扩展点接口名>$Adpative implements <扩展点接口> {
    public <有@Adaptive注解的接口方法>(<方法参数>) {
        if(是否有URL类型方法参数?) 使用该URL参数
        else if(是否有方法类型上有URL属性) 使用该URL属性
        # <else 在加载扩展点生成自适应扩展点类时抛异常,即加载扩展点失败!>
         
        if(获取的URL == null) {
            throw new IllegalArgumentException("url == null");
        }
 
              根据@Adaptive注解上声明的Key的顺序,从URL获致Value,作为实际扩展点名。
               如URL没有Value,则使用缺省扩展点实现。如没有扩展点, throw new IllegalStateException("Fail to get extension");
 
               在扩展点实现调用该方法,并返回结果。
    }
 
    public <有@Adaptive注解的接口方法>(<方法参数>) {
        throw new UnsupportedOperationException("is not adaptive method!");
    }
}
      >getAdaptiveExtension() //cachedAdaptiveInstance缓存adaptive实例
          >createAdaptiveExtension()//若实例不存在则创建实例
             >getAdaptiveExtensionClass()//cachedAdaptiveClass缓存adaptive的Class类
                >getExtensionClasses()
                    >loadExtensionClasses()
                        >loadFile
                >createAdaptiveExtensionClass//如果不存在adaptive的类,创建adaptive的Class类
                    >createAdaptiveExtensionClassCode()//自动生成和编译一个动态的adpative类,这个类是一个代理类
                    >ExtensionLoader.getExtensionLoader(com.alibabadubbo.common.compiler) //获取一个compiler的装饰类 
                    > compiler.compile(code, classLoader)
             >injectExtension//IOC注入

三. IOC和AOP

四. 动态编译

javassist是一个字节码编辑工具
使用方法:

   ClassPool pool = ClassPool.getDefatult();
   CtClass = pool.makeClass("com.sutdy.javass.Test")
   //添加属性
   CtField enameFiled = new CtField(pool.getClass("java.lang.String"), "enamne", ctlass);
   ctClass.addField(enameFiled);
   Class<?> clazz = ctClass.toClass;
   

五. Dubbo和Spring

  • 完成一个spring的自定义配置一般需要以下5个步骤:
    1)设计配置属性和JavaBean
    2)编写XSD文件(XML Schema) 它就是校验XML定义一些列的语法来规范XML
    3)编写NanesepaceHandler和BeanDefinitionParser完成解析工作
    4)编写spring.handlers和spring.schemas串联起所有部件
    5)在bean文件中应用

六. 服务发布

  • 发布步骤

1)暴露本地服务

	Export dubbo service com.alibaba.dubbo.demo.DemoService to local registry, dubbo version: 2.0.0, current host: 127.0.0.1

2)暴露远程服务

	Export dubbo service com.alibaba.dubbo.demo.DemoService to url dubbo://192.168.100.38:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=8484&side=provider&timestamp=1473908495465, dubbo version: 2.0.0, current host: 127.0.0.1
	Register dubbo service com.alibaba.dubbo.demo.DemoService url dubbo://192.168.100.38:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&monitor=dubbo%3A%2F%2F192.168.48.117%3A2181%2Fcom.alibaba.dubbo.registry.RegistryService%3Fapplication%3Ddemo-provider%26backup%3D192.168.48.120%3A2181%2C192.168.48.123%3A2181%26dubbo%3D2.0.0%26owner%3Dwilliam%26pid%3D8484%26protocol%3Dregistry%26refer%3Ddubbo%253D2.0.0%2526interface%253Dcom.alibaba.dubbo.monitor.MonitorService%2526pid%253D8484%2526timestamp%253D1473908495729%26registry%3Dzookeeper%26timestamp%3D1473908495398&owner=william&pid=8484&side=provider&timestamp=1473908495465 to registry registry://192.168.48.117:2181/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&backup=192.168.48.120:2181,192.168.48.123:2181&dubbo=2.0.0&owner=william&pid=8484&registry=zookeeper&timestamp=1473908495398, dubbo version: 2.0.0, current host: 127.0.0.1

3)启动netty

	Start NettyServer bind /0.0.0.0:20880, export /192.168.100.38:20880, dubbo version: 2.0.0, current host: 127.0.0.1

4)打开连接zk

INFO zookeeper.ClientCnxn: Opening socket connection to server /192.168.48.117:2181

5)到zk注册

创建dubbo/com.alibaba.dubbo.demo.DemoService/provider持久化节点
在provider目录下创建一个代ip地址的临时节点

Register: dubbo://192.168.100.38:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=8484&side=provider&timestamp=1473908495465, dubbo version: 2.0.0, current host: 127.0.0.1

6)监听zk
首先创建一个dubbo/com.alibaba.dubbo.demo.DemoService/configurators持久化节点
然后订阅该节点的childlistren
订阅处理者:缓存configrators的内容到本地文件中

Subscribe: provider://192.168.100.38:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=8484&side=provider&timestamp=1473908495465, dubbo version: 2.0.0, current host: 127.0.0.1
Notify urls for subscribe url provider://192.168.100.38:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=8484&side=provider&timestamp=1473908495465, urls: [empty://192.168.100.38:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=8484&side=provider&timestamp=1473908495465], dubbo version: 2.0.0, current host: 127.0.0.1

暴露本地服务和暴露远程服务的区别是什么?
1.暴露本地服务:指暴露在用一个JVM里面,不用通过调用zk来进行远程通信。例如:在同一个服务,自己调用自己的接口,就没必要进行网络IP连接来通信。
2.暴露远程服务:指暴露给远程客户端的IP和端口号,通过网络来实现通信。

zk持久化节点 和临时节点有什么区别?
持久化节点:一旦被创建,触发主动删除掉,否则就一直存储在ZK里面。
临时节点:与客户端会话绑定,一旦客户端会话失效,这个客户端端所创建的所有临时节点都会被删除。

六. 服务降级

怎么做服务降级
空谈误国,实战兴邦,光知道思维导图上的这些设计原则还不行,我们以dubbo为例,实战一下服务降级.首先dubbo中的服务降级分成两个

屏蔽(mock=force)
容错(mock=fail)

mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。

还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值