微信公衆號:[中間件興趣圈]
做者簡介:《RocketMQ技術內幕》做者java
背景:基於Dubbo服務的治理,是否能夠支持業務級別的灰度發佈、是否基於業務參數的路由轉發。例如以GIS爲例,當發佈一個新版本時,是否能夠以按照解析地址或合做夥伴來區分,版本發佈之初,只但願地址爲:廣東省的解析請求發送到新版本,而其餘的地址請求仍是使用舊版;或者根據合做夥伴例如UCP(優享寄)的請求轉發到新版本服務器,其餘合做夥伴仍是轉發到舊版,實現業務級別的灰度發佈,控制新版本的影響範圍。例如OMS系統,能夠根據合做夥伴,將重量級客戶的請求轉發到單獨的服務器集羣,確保其高可用。
本文將對上述議題結合Dubbo提供的功能,提出設計方案。算法
Dubbo的服務調用原理圖:服務器
客戶端在發起RPC服務調用以前,在客戶端首先從服務器列表中選擇一個服務調用者,包含以下關鍵角色:
一、Directory
服務的動態發現,一般基於註冊中心進行服務的動態註冊與發現,其具體實現類爲RegistryDirectory。微信
二、Router
路由實現,其含義是根據Directory發現的全部服務提供者列表中,進行路由選擇,也就是根據必定的路由規則選擇合適的服務提供者,爲Directory發現的服務提供者列表子集,能夠基於Condition或腳本(默認爲JS腳本,其實現類爲ScriptRouter)。負載均衡
三、LoadBalance
負載均衡機制,其做用主要是根據負載均衡算法(隨機、輪詢)等算法,從(Directory-->Router)中返回的服務提供者列表中選擇一個服務提供者,進行本次的RPC服務調用。運維
四、Cluster
集羣(容錯機制),就是當從服務提供者列表中按照負載均衡算法選擇一個服務提供者,進行RPC服務調用後,發送了異常後的策略,例如failover(重試)、failfast(快速失敗)等。ide
服務的灰度發佈,其目標是但願根據請求,某些請求走新版本服務器,某些請求走舊版本服務器,其本質就是路由機制,即經過必定的條件來縮小服務的服務提供者列表,正好與Dubbo的Router相吻合。設計
有關於Dubbo的Router機制,請參考官方文檔第【4六、4七、48】頁,若是想從源碼的角度瞭解其實現機制,請參考Dubbo路由機制概述3d
有了理論支持,下文將根據上述理論進行實戰。code
本示例代碼須要完成的任務是,對DemoService#createUser服務,其用戶機構ID(orgId)爲1的走新版本(當前服務提取者列表的最後一臺服務器),其餘的請求走全部的服務器(除最後一臺服務器)。
因爲是須要基於請求參數,本文給出基於JS腳本的路由機制,首先,當前版本的dubbo-admin能夠後臺頁面維護基於條件表達式的路由規則,其界面以下:
備註:而且當前dubbo-admin版本,並不支持基於JS表達式的路由規則,若是手動創建基於表達式的路由規則,其頁面將沒法列出路由表達式,其界面以下:
各個項目,各個服務須要根據自身的需求,定義以下腳本:
1/** 2 * DemoService router,針對不一樣的方法,可能須要各自提供,主要是參數的獲取,不一樣的過濾規則 3 * 針對參數進行路由過濾 4 * 5 * 本示例針對 DemoSerivce# ResponseResult createUser(User user) 方法,根據user的orgId進行路由選擇 6 * @param invokers 7 * @param invocation 8 * @param context 9 * @returns 10 */ 11function demoService_createUser_router(invokers, invocation, context) { 12 if(invokers == null || invokers.size() < 1) { 13 return invokers; 14 } 15 16 if(!"createUser".equals(invocation.getMethodName())) { // 若是方法不匹配,默認無條件經過該路由規則 17 return invokers; 18 } 19 20 var availableInvokers = new java.util.ArrayList(invokers.size()); 21 for (var i=0;i<invokers.size(); i++) { // 先選擇可用的服務提供者列表 22 if(invokers.get(i).isAvailable()) { 23 availableInvokers.add(invokers.get(i)); 24 } 25 } 26 27 var invArguments = invocation.getArguments(); 28 if(invArguments == null || invArguments.length == 0) { // 若是參數爲空,沒法根據參數進行路由選擇 29 return availableInvokers; 30 } 31 32 // 獲取須要進行路由的參數,這裏使用第一個參數 ,這裏各自根據各自的業務 進行獲取,本實例默認使用第一個參數 33 var firstArgument = invArguments[0]; 34 var orgId = firstArgument == null ? "" : firstArgument.getOrgId(); 35 36 37 if(orgId == 1 || orgId == "1") { // 若是orgId == 1 ,只走最後一個節點,其他的走其餘節點 38 var selectInvokers = new java.util.ArrayList(1); 39 selectInvokers.add(availableInvokers.get(availableInvokers.size()-1)); 40 return selectInvokers; 41 } else { 42 var selectInvokers = new java.util.ArrayList(availableInvokers.size()-1); 43 for(var i=0;i<availableInvokers.size()-1; i++) { 44 selectInvokers.add(availableInvokers.get(i)); 45 } 46 return selectInvokers; 47 } 48}
上文已經說明,目前的dubbo-admin不支持在界面上註冊路由規則,現給出基於JAVA代碼來編寫註冊程序:
1public static void main(String[] args) throws Exception{ 2 URL registryUrl = URL.valueOf("zookeeper://127.0.0.1:2181"); 3 ZookeeperRegistryFactory zookeeperRegistryFactory = new 4 ZookeeperRegistryFactory(); 5 zookeeperRegistryFactory.setZookeeperTransporter(new 6 CuratorZookeeperTransporter()); 7 Registry zookeeperRegistry = (ZookeeperRegistry) 8 zookeeperRegistryFactory.createRegistry(registryUrl); 9 URL routerURL = 10 URL.valueOf("script://0.0.0.0/com.alibaba.dubbo.demo.Demo 11 Service?category=routers&dynamic=false&enabled=true&fo 12 rce=false&name=demoService_createUser_router&priority= 13 0&runtime=true"); 14 routerURL = routerURL.addParameter("rule", 15 URL.encode(get_demoService_createUser_router())); 16 zookeeperRegistry.register(routerURL); // 註冊 17 // zookeeperRegistry.unregister(routerURL); // 取消註冊 18}
一旦運行上述代碼,將會動態註冊URL,服務提供者無需重啓,下次服務調用後會自動生效(其背後原理是基於註冊中心的動態發現)。
上述示例代碼,我已經在本地環境,已能成功運行,並達到預期效果,公司項目須要根據自身的特色,特別服務方法的參數(例如合做夥伴ID的獲取方式),以及路由需求來定製編寫其路由腳本(js腳本)。
上述展現了Dubbo服務基於業務灰度發佈的方案,以及基於合做夥伴的服務隔離機制(根據服務調用業務參數來決定服務調用者的篩選)。主要是展現了基於腳步的路由規則,其條件表達式的路由規則請參考其Demo,其核心理論支持是Dubbo提供的Router,在進行負載均衡前,根據路由規則對服務提供者列表進行篩選。
最後說明一下:本方案主要展現基於腳本的路由選擇策略,一般在實際使用過程當中基於條件路由較多,例如基於消費者IP進行條件選擇。
更多文章請關注微信公衆號:
廣告:做者的新書《RocketMQ技術內幕》已上市
《RocketMQ技術內幕》已出版上市,目前可在主流購物平臺(京東、天貓等)購買,本書從源碼角度深度分析了RocketMQ NameServer、消息發送、消息存儲、消息消費、消息過濾、主從同步HA、事務消息;在實戰篇重點介紹了RocketMQ運維管理界面與當前支持的39個運維命令;並在附錄部分羅列了RocketMQ幾乎全部的配置參數。本書獲得了RocketMQ創始人、阿里巴巴Messaging開源技術負責人、Linux OpenMessaging 主席的高度承認並做序推薦。目前是國內第一本成體系剖析RocketMQ的書籍。
新書7折優惠!7折優惠!7折優惠!
推薦關注微信公衆號:RocketMQ官方微信公衆號