新聞中心
介紹
策略模式
這個毫無爭議,Dubbo是基于SPI來擴展的,SPI就是典型的策略模式。

專注于為中小企業(yè)提供網(wǎng)站設(shè)計、成都做網(wǎng)站服務(wù),電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業(yè)烏當免費做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了近1000家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴充和轉(zhuǎn)變。
Dubbo中可替換的組件太多了,例如負載均衡策略
| 實現(xiàn)類 | 解釋 |
|---|---|
| RandomLoadBalance | 隨機策略(默認) |
| RoundRobinLoadBalance | 輪詢策略 |
| LeastActiveLoadBalance | 最少活躍調(diào)用數(shù) |
| ConsistentHashLoadBalance | 一致性hash策略 |
工廠模式
「簡單工廠模式」:提供一個方法,返回創(chuàng)建好的對象
- public class VideoFactory {
- public static Video getVideo(String type) {
- if ("java".equalsIgnoreCase(type)) {
- return new JavaVideo();
- } else if ("python".equalsIgnoreCase(type)) {
- return new PythonVideo();
- }
- return null;
- }
- }
「工廠方法模式」:當工廠想提供更多產(chǎn)品時,還得對創(chuàng)建過程進行修改,因此抽象出一個工廠類,當增加一種產(chǎn)品,就增加一個工廠類(繼承抽象工廠類或?qū)崿F(xiàn)接口)。這樣就實現(xiàn)了對擴展開發(fā),對修改關(guān)閉
- public abstract class VideoFactory {
- public abstract Video getVideo();
- }
- public class JavaVideoFactory extends VideoFactory {
- public Video getVideo() {
- return new JavaVideo();
- }
- }
- public class Test {
- public static void main(String[] args) {
- VideoFactory videoFactory = new JavaVideoFactory();
- Video video = videoFactory.getVideo();
- // 學習Java視頻
- video.study();
- }
- }
「抽象工廠模式」:當生產(chǎn)的產(chǎn)品較多時,如果我們用工廠方法模式會造成類爆照,此時我們就可以把相關(guān)的產(chǎn)品生產(chǎn)放到一個工廠類中
- public abstract class CourseFactory {
- public abstract Video getVideo();
- public abstract Article getArticle();
- }
- public class JavaCourseFactory extends CourseFactory {
- public Video getVideo() {
- return new JavaVideo();
- }
- public Article getArticle() {
- return new JavaArticle();
- }
- }
因為JavaVideo和JavaArticle都是Java相關(guān)的資料,所以可以用一個工廠類來生產(chǎn)。如果用工廠方法模式來設(shè)計的話,JavaVideo和JavaArticle都會有一個對應(yīng)的工廠類
簡單工廠模式
- public class LoggerFactory {
- public static Logger getLogger(Class> key) {
- return LOGGERS.computeIfAbsent(key.getName(), name -> new FailsafeLogger(LOGGER_ADAPTER.getLogger(name)));
- }
- }
工廠方法模式
Dubbo可以對結(jié)果進行緩存,緩存的策略有很多種,一種策略對應(yīng)一個緩存工廠類
- @SPI("lru")
- public interface CacheFactory {
- @Adaptive("cache")
- Cache getCache(URL url, Invocation invocation);
- }
抽象工廠模式
在RPC框架中,客戶端發(fā)送請求和服務(wù)端執(zhí)行請求的過程都是由代理類來完成的。客戶端的代理對象叫做Client Stub,服務(wù)端的代理對象叫做Server Stub。
- @SPI("javassist")
- public interface ProxyFactory {
- // 針對consumer端,創(chuàng)建出代理對象
- @Adaptive({Constants.PROXY_KEY})
T getProxy(Invoker invoker) throws RpcException; - // 針對consumer端,創(chuàng)建出代理對象
- @Adaptive({Constants.PROXY_KEY})
T getProxy(Invoker invoker, boolean generic) throws RpcException; - // 針對provider端,將服務(wù)對象包裝成一個Invoker對象
- @Adaptive({Constants.PROXY_KEY})
Invoker getInvoker(T proxy, Class type, URL url) throws RpcException; - }
單例模式
服務(wù)導出的過程中,為了防止開啟多個NettyServer,用了單例模式
- private void openServer(URL url) {
- // find server.
- String key = url.getAddress();
- //client can export a service which's only for server to invoke
- boolean isServer = url.getParameter(Constants.IS_SERVER_KEY, true);
- if (isServer) {
- ExchangeServer server = serverMap.get(key);
- if (server == null) {
- synchronized (this) {
- server = serverMap.get(key);
- if (server == null) {
- // 創(chuàng)建服務(wù)器實例
- serverMap.put(key, createServer(url));
- }
- }
- } else {
- // server supports reset, use together with override
- server.reset(url);
- }
- }
- }
裝飾者模式
Dubbo中網(wǎng)絡(luò)傳輸層用到了Netty,當我們用Netty開發(fā)時,一般都是寫多個ChannelHandler,然后將這些ChannelHandler添加到ChannelPipeline上,就是典型的責任鏈模式
但是Dubbo考慮到有可能替換網(wǎng)絡(luò)框架組件,所以整個請求發(fā)送和請求接收的過程全部用的都是裝飾者模式。即只有NettyServerHandler實現(xiàn)的接口是Netty中的ChannelHandler,剩下的接口實現(xiàn)的是Dubbo中的ChannelHandler
如下是服務(wù)端消息接收會經(jīng)過的ChannelHandler
代理模式
前面說過了哈,Client Stub和Server Stub都是代理對象
適配器模式
Dubbo可以支持多個日志框架,每個日志框架的實現(xiàn)都有對應(yīng)的Adapter類,為什么要搞Adapter類呢,因為Dubbo中日志接口Logger用的是自己的,而實現(xiàn)類是引入的。但這些日志實現(xiàn)類的等級和Dubbo中定義的日志等級并不完全一致,例如JdkLogger中并沒有trace和debug這個等級,所以要用Adapter類把Logger中的等級對應(yīng)到實現(xiàn)類中的合適等級
- public interface Logger
- // 省略部分代碼
- void trace(String msg);
- void debug(String msg);
- void info(String msg);
- void warn(String msg);
- }
| Dubbo接口中定義的日志等級 | JdkLogger對應(yīng)的日志等級 | Slf4jLogger對應(yīng)的日志等級 |
|---|---|---|
| trace | finer | trace |
| debug | finer | debug |
| info | info | info |
觀察者模式
在Dubbo中提供了各種注冊中心的實現(xiàn),類圖如下。AbstractRegistry對注冊中心的內(nèi)容進行了緩存,這樣能保證當注冊中心不可用的時候,還能正常提供服務(wù)
「既然對注冊中心的內(nèi)容進行了緩存,那么注冊中心的內(nèi)容發(fā)生改變的時候,怎么通知客戶端呢?」
例如客戶端從注冊中心獲取到服務(wù)端的地址,并緩存到本地,如果服務(wù)端宕機了,本地緩存怎么清除呢?此時就得需要對有可能變動的節(jié)點進行訂閱。當節(jié)點發(fā)生變化的時候,就能收到通知,這樣就能更新本地緩存。
NotifyListener就是接收節(jié)點變動的接口,各種注冊中心的節(jié)點發(fā)生變化都會主動回調(diào)這個接口
- public interface RegistryService {
- // 注冊
- void register(URL url);
- // 注銷
- void unregister(URL url);
- // 訂閱,訂閱的數(shù)據(jù)發(fā)生變化,會主動通知NotifyListener#notify方法
- void subscribe(URL url, NotifyListener listener);
- // 退訂
- void unsubscribe(URL url, NotifyListener listener);
- // 查找服務(wù)地址
- List
lookup(URL url); - }
責任鏈模式
代理對象(Client Stub或者Server Stub)在執(zhí)行的過程中會執(zhí)行所有Filter的invoke方法,但是這個實現(xiàn)方法是對對象不斷進行包裝,看起來非常像裝飾者模式,但是基于方法名和這個Filter的功能,我更覺得這個是責任鏈模式
- private static
Invoker buildInvokerChain(final Invoker invoker, String key, String group) { - Invoker
last = invoker; - // 獲取自動激活的擴展類
- List
filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group); - if (!filters.isEmpty()) {
- for (int i = filters.size() - 1; i >= 0; i--) {
- final Filter filter = filters.get(i);
- final Invoker
next = last; - last = new Invoker
() { - // 省略部分代碼
- @Override
- public Result invoke(Invocation invocation) throws RpcException {
- // filter 不斷的套在 Invoker 上,調(diào)用invoke方法的時候就會執(zhí)行filter的invoke方法
- Result result = filter.invoke(next, invocation);
- if (result instanceof AsyncRpcResult) {
- AsyncRpcResult asyncResult = (AsyncRpcResult) result;
- asyncResult.thenApplyWithContext(r -> filter.onResponse(r, invoker, invocation));
- return asyncResult;
- } else {
- return filter.onResponse(result, invoker, invocation);
- }
- }
- };
- }
- }
- return last;
- }
本文轉(zhuǎn)載自微信公眾號「Java識堂」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系Java識堂公眾號。
本文題目:Dubbo中用到了哪些設(shè)計模式?
轉(zhuǎn)載來于:http://www.fisionsoft.com.cn/article/cdieedo.html


咨詢
建站咨詢
