背景介紹
如今不少的公司都在用dubbo、springcloud作爲服務化/微服務的開發框架,服務化以後應用愈來愈多,鏈路愈來愈長,服務環境的治理變的很困難。好比:研發團隊的人不少的,同時有幾個分支在開發和測試,會形成多個同名的服務存在,爲了不不一樣feature之間的服務不串調,不少研發人員會改服務的版本號來避免這種狀況;還有一種狀況是由於修改服務版本號,調用鏈鏈路上全部的節點都須要修改,存在浪費機器資源的現象。javascript
需求場景描述
- 穩定的測試環境通常是有測試的同窗維護的,上面的代碼通常是驗證完成(即將上線)的分支,或者就是和線上代碼保持一致的分支(基準代碼);
- 下圖中需求1是正在開發的某個需求,它涉及了2個須要改動的應用A和B,因爲他們在需求1裏(代碼也切分支),咱們稱需求1裏面的應用A爲A1,需求1裏面的應用B爲B1;
- 同理,需求2也是正在開發的某個需求,由於它和需求1同時開發,涉及的應用也有重合,因此稱爲併發需求。需求2中的應用A爲A2,應用B爲B2,應用E爲E2;
- 在不修改服務版本號的狀況下,需求1的研發人員但願A1直接調用下游B,而後B調用C1,由於應用B、C、D在需求1裏面是沒有代碼變動的,因此完整的調用鏈路以下:A1->B->C1->D->E
- 需求2中有代碼變動的應用是A二、B二、E2,不須要更變的是C、D,因此完成的調用鏈路以下:A2->B2->C->D->E2
總結起來:
研發只但願調用本需求內應用,若是鏈路中某個應用沒有代碼變動,則調用穩定環境中的應用(保證鏈路能走通,而且把這種邏輯路由的關係傳遞到下游應用中)java
談dubbo路由
dubbo框架內部自帶路由的,它支持2種路由規則:ConditionRouter、ScriptRouter,MockInvokersSelector暫時不討論。git
一、 其中ConditionRouter表示條件路由,條件表達式以 => 分割爲whenRule和thenRule:
例子:*github
condition://0.0.0.0/com.foo.BarService?category=routers&dynamic=false&rule=" + URL.encode("host = 10.20.153.10 => host = 10.20.153.11"spring
- 從url根據RULE_KEY獲取路由條件路由內容
- rule.indexOf("=>") 分割路由內容: =>前面是消費者條件(when),=>後面是provider的條件(then)
- 分別調用parseRule(rule) 解析路由爲whenRule和thenRules
ConditionRouter執行route方法:
- 若是url不知足when條件即過來條件, 不過濾返回全部invokers
- 遍歷全部invokers判斷是否知足then條件, 將知足條件的加入集合result
- Result不爲空,有知足條件的invokers返回
- Result爲空, 沒有知足條件的invokers, 判斷參數FORCE_KEY是否強制過來,若是強制過濾返回空, 不是返回全部即不過濾
ConditionRouter的點評
ConditionRouter並非適合咱們的需求,由於咱們須要是配合簡單運維實現自動路由,不須要開發人員寫額外代碼和配置,很顯然ConditionRouter=>後面的then條件是固定的一個provider或者一組provider,而不能動態路由;第二點是ConditionRouter在穩定測試環境的應用上也須要在URL裏面打上路由標識,這就違反了咱們初衷:不須要開發人員寫額外代碼和配置ruby
二、 ScriptRouter表示腳本路由
經過url的RULE_KEY參數獲取腳本內容,而後經過java的腳本引擎執行腳本代碼, dubbo的測試用例都是經過javascript做爲腳本可是理論上也支持groovy, jruby腳本併發
- 從url獲取腳本類型javascript, groovy等等
- 從url根據RULE_KEY獲取路由規則內容
- 根據腳本類型獲取java支持的腳本執行引擎
ScriptRouter的點評
ScriptRouter雖然比ConditionRouter靈活,能夠在消費端執行腳原本控制路由的邏輯,可是仍是有一樣的問題,對於穩定的測試環境裏的應用也須要配置路由腳本,不能作到真正的少配置、少運維、少寫額外代碼框架
邏輯路由的方案
咱們分析了場景和需求,又分析現有的dubbo路由方案的不知足,如今來來看一下一種可行的方案:運維
- 邏輯路由provider和consumer都經過URL來獲取路由標識
- 最小運維開支:經過申請應用環境的時候,在機器打上環境變量
- 最小的dubbo框架改動:在LoadBalance和AbstractClusterInvoker上修改邏輯路由方案
show me code
具體實現的代碼,我放在github上,變動也不大,分支ide
- 在LoadBalance和AbstractClusterInvoker上修改邏輯路由主要邏輯
- 在provider註冊服務的URL時,加上邏輯路由的標識
- dubbox新增長了一個依賴:logical-router,這是我本身寫的小的jar包,方便以後作擴展(好比rest入口的應用程序,自啓動的應用程序等等)
- 運維相關:只須要給申請相同的邏輯路由標識應用的機器,打上相同的環境變量:LOGICAL_ROUTER_ENV
diff文件
更方便的查看變動:diff文件