当前位置: 首页 > 科技观察

Dubbo使用了哪些设计模式?

时间:2023-03-15 14:11:23 科技观察

引入策略模型是无可争议的。Dubbo基于SPI进行扩展,SPI是典型的策略模型。Dubbo中可以替换的组件太多,比如负载均衡策略实现类讲解RandomLoadBalance随机策略(默认)RoundRobinLoadBalance轮询策略LeastActiveLoadBalance最小活跃调用数ConsistentHashLoadBalance一致性哈希策略工厂模式“简单工厂模式”:提供方法,返回创建的对象工厂方法模式”:当工厂要提供更多的产品时,要修改创建过程,所以抽象出一个工厂类,当增加一个产品时,再增加一个工厂类(继承抽象工厂类或实现界面)。这样就现实了对扩展开发,对修改关闭publicabstractclassVideoFactory{publicabstractVideogetVideo();}publicclassJavaVideoFactoryextendsVideoFactory{publicVideogetVideo(){returnnewJavaVideo();}}publicclassTest{publicstaticvoidmain(StringVideo[]oryvideo.VideoFactory){=FactoryJvideoFactory.VideoFactory();getVideo();//学习Java视频video.study();}}《抽象工厂模式》:当生产的产品很多时,如果我们使用工厂方法模式,会造成类爆炸。这时候,我们可以把相关Product的制作放在一个工厂类中),所以你可以使用工厂类来生产。如果使用工厂方法模式来设计,JavaVideo和JavaArticle都会有对应的工厂类简单工厂模式.getLogger(name)));}}工厂方法方式dubbo可以缓存结果,缓存的策略有很多种,一种策略对应一个缓存工厂类@SPI("lru")publicinterfaceCacheFactory{@Adaptive("cache")CachegetCache(URLurl,Invocationinvocation);}抽象工厂模式在RPC框架中,客户端发送请求和服务器执行请求的过程都是由代理类完成的。客户端的代理对象称为ClientStub,服务器的代理对象称为ServerStub。@SPI("javassist")publicinterfaceProxyFactory{//为消费端创建代理对象@Adaptive({Constants.PROXY_KEY})TgetProxy(Invokerinvoker)throwsRpcException;//为消费端创建代理Object@Adaptive({Constants.PROXY_KEY})TgetProxy(Invokerinvoker,booleangeneric)throwsRpcException;//对于provider端,将服务对象包装成Invoker对象@Adaptive({Constants.PROXY_KEY})InvokergetInvoker(Tproxy,Classtype,URLurl)throwsRpcException;}在导出单例模式服务的过程中,为了防止开启多个NettyServer,单例模式privatevoidopenServer(URLurl){//查找服务器。Stringkey=url.getAddress();//clientcanexportaservicewhich'onlyforservertoinvokebooleanisServer=url.getParameter(Constants.IS_SERVER_KEY,true);if(isServer){ExchangeServerserver=serverMap.get(key);if(server==null){synchronized(this){server=serverMap.get(key);if(server==null){//创建服务器实例serverMap.put(key,createServer(url));}}}else{//serversupportsreset,usetogetherwithoverrideserver.reset(url);}}}装饰器模式下的网络传输层Dubbo使用的是Netty,当我们使用在开发Netty的时候,常见的是编写多个ChannelHandlers,然后将这些ChannelHandlers添加到ChannelPipeline中,这是典型的责任链模型。但是Dubbo考虑到替换网络框架组件的可能性,所以整个发送和接收请求的过程都采用了装饰器模式,即只有NettyServerHandler实现的接口是Netty中的ChannelHandler,其余接口由Dubbo中的ChannelHandler。下面是服务器接收消息的ChannelHandler代理模式。前面提到,ClientStub和ServerStub是一种代理对象适配器模式。Dubbo可以支持多种日志框架。每个日志框架的实现都有一个对应的Adapter类。为什么要使用Adapter类?因为Dubbo中的日志接口Logger使用的是自己的,而实现类是引入的。但是这些日志实现类的级别与Dubbo中定义的日志级别并不完全一致。比如JdkLogger中没有trace和debug级别,那么应该使用Adapter类将Logger中的级别映射到实现类中的相应级别publicinterfaceLogger//省略部分代码voidtrace(Stringmsg);voiddebug(Stringmsg);voidinfo(Stringmsg);voidwarn(Stringmsg);}Dubbo接口中定义的日志级别对应JdkLogger的日志级别Slf4jLogger对应的日志级别tracefinertracedebugfinerdebuginfoinfo观察者模式提供各种注册中心实现在Dubbo中,类图如下。AbstractRegistry缓存注册中心的内容,保证在注册中心不可用时,仍然可以正常提供服务。“既然缓存了注册表的内容,那么当注册表的内容发生变化时,如何通知客户呢?最后呢?”例如,客户端从注册中心获取服务器的地址,缓存到本地。如果服务器宕机,如何清除本地缓存?这时候就需要订阅可能发生变化的节点。当节点发生变化时,您可以收到通知,以便更新本地缓存。NotifyListener是接收节点变化的接口。当各个注册中心的节点发生变化时,会主动回调该接口。主动通知NotifyListener#notifymethodvoidsubscribe(URLurl,NotifyListenerlistener);//取消订阅voidunsubscribe(URLurl,NotifyListenerlistener);//查找服务地址Listlookup(URLurl);}责任链模式代理对象(ClientStub或ServerStub)在执行过程中会执行Filter所有的invoke方法,但是这个实现方法是不断的包裹对象,看起来很像装饰器模式,但是根据方法名和Filter的作用,我觉得这是责任链模式privatestaticInvokerbuildInvokerChain(finalInvokerinvoker,Stringkey,Stringgroup){Invokerlast=invoker;//获取自动激活的扩展类Listfilters=ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(),key,group);if(!filters.isEmpty()){for(inti=filters.size()-1;i>=0;i--){finalFilterfilter=filters.get(i);finalInvokernext=last;last=newInvoker(){//省略par代码的t@OverridepublicResultinvoke(Invocationinvocation)throwsRpcException{//不断在Invoker上设置过滤器,当invoke方法被调用时,会执行filter的invoke方法(r,invoker,invocation));returnasyncResult;}else{returnfilter.onResponse(result,invoker,invocation);}}};}}returnlast;}本文转载自微信公众号「Java知堂」,你可以关注下方二维码转载请联系爪哇石塘公众号。