目录
Dubbo集群容错策略
Dubbo动态代理策略
Failover Cluster模式
失败自动切换自动重试其他机器(默认),常见于读操作,可以通过以下几种方式配置重试次数:
//或者
//或者
Failfast Cluster模式
一次调用失败就立即失败,常见于非幂等性的写操作,比如新增一条记录(调用失败就立即失败)
Failsafe Cluster模式
出现异常时忽略掉,常用于不重要的接口调用,比如记录日志。配置如下:
//或者
Failback Cluster模式
失败时后台自动记录请求,然后定时重发比较适合于写消息队列这种。
Forking Cluster模式
并行调用多个provider,只要一个成功就立即返回。常用于实时性要求比较高的读操作,但是会浪费更多的服务资源,可通过forks="2"
来设置最大并行数。
Broadcast Cluster模式
逐个调用所有的provider。任何一个provider出错则报错(从 2.1.0
版本开始支持)。通常用于通知所有提供者更新缓存或日志等本地资源信息。
关于dubbo集群容错策略更加详细的描述,查看官网http://dubbo.apache.org/zh-cn/docs/source_code_guide/cluster.html 。
默认使用javassist动态字节码生成,创建代理类。也可以通过spi扩展机制配置自己的动态代理策略。
Dubbo的SPI思想:SPI(Service Provider Interface)
,比如有个接口,这个接口有3个实现类,系统运行的时候对这个接口到底选择哪个实现类呢?这就需要spi了,需要根据指定的配置或者是默认的配置,去找到对应的实现类加载进来,然后才可以调用到这个实现类的实例对象。比如有一个接口A。A1/A2/A3分别是接口A的不同实现。通过配置接口A = 实现 A2
,在系统实际运行的时候,会加载配置,用实现A2实例化一个对象来提供服务。spi机制一般用在哪儿?插件扩展的场景,比如开发了一个给别人使用的开源框架,如果想让别人自己写个插件,在开源框架的基础上扩展某个功能,这个时候spi思想就用上了。
Java spi思想的体现
spi经典的思想体现,比如jdbc,Java定义了一套jdbc的接口,但是Java并没有提供jdbc的实现类。但是实际上项目跑的时候,要使用jdbc接口的哪些实现类呢?根据自己使用的数据库比如mysql就将mysql-jdbc-connector.jar
引入进来,oracle就将oracle-jdbc-connector.jar
引入进来,在系统跑的时候会在底层使用引入的那个jar中提供的实现类。
dubbo也用了spi思想,不过没有用jdk的spi机制,是自己实现的一套spi机制。
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
Protocol接口在系统运行的时候,dubbo会判断一下应该选用这个Protocol 接口的哪个实现类来实例化对象来使用。它会去找一个配置的Protocol,将Protocol实现类加载到jvm中来,然后实例化对象。上面那行代码就是dubbo里大量使用的,对很多组件都是保留一个接口和多个实现,然后在系统运行的时候动态根据配置去找到对应的实现类。如果没配置就走默认的实现。
@SPI("dubbo")
public interface Protocol {
int getDefaultPort();
@Adaptive
Exporter export(Invoker invoker) throws RpcException;
@Adaptive
Invoker refer(Class type, URL url) throws RpcException;
void destroy();
}
dubbo自己的jar里,在/META_INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol
文件中
dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
http=com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol
Dubbo的spi机制默认其实就是Protocol接口, @SPI("dubbo")
说的是,通过SPI机制来提供实现类,实现类通过dubbo作为默认key去配置文件里找到,配置文件名称与接口定名一样通过dubbo作为key可以找到默认的实现类就是com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
。如果想要动态替换掉默认的实现类,需要使用@Adaptive
接口,Protocol接口中有两个方法加了@Adaptive
注解,就是说那俩接口会被代理实现。比如这个Protocol接口搞了俩@Adaptive
注解标注了方法,在运行的时候会针对Protocol生成代理类,这个代理类在运行的时候动态根据url中的 protocol来获取那个key,默认是dubbo,也可以自己指定,如果指定了别的key,就会获取别的实现类的实例。
如何扩展dubbo中的组件
自己写个工程,要是那种可以打成jar包的,里面的src/main/resources
目录下,搞一个META-INF/services
,里面放个文件叫: com.alibaba.dubbo.rpc.Protocol
,文件里搞一个my=com.bingo.MyProtocol
。把jar弄到nexus私服里去。然后自己搞一个dubbo provider
工程,在这个工程里面依赖自己搞的那个jar,然后在spring配置文件里配置:
provider启动的时候,就会加载到我们jar包里的my=com.bingo.MyProtocol
这行配置,接着会根据配置使用定义好的MyProtocol了,通过上述方式,可以替换掉大量的dubbo内部的组件,写一个自己的jar包,然后配置一下即可。
dubbo里面提供了大量的类似上面的扩展点,如果要扩展一个东西,只要写个jar,在consumer或者是provider工程依赖那个jar,在jar里指定目录下配置好接口名称对应的文件,里面通过key=实现类
。然后对于对应的组件,类似
用那个key对应的实现类来实现某个接口,可以自己去扩展dubbo的各种功能,提供自己的一些实现。