角色
registry
consumer
provider
monitor
- 启动流程
内核
一. 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×tamp=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×tamp=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®istry=zookeeper×tamp=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×tamp=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×tamp=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×tamp=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×tamp=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 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。