開(kāi)發(fā)痛點(diǎn)
先來(lái)張圖看下吧。

1. 邏輯散亂到幾個(gè)service中,大量的transaction script類代碼。
2. 一部分邏輯就花了200多行,大量平鋪代碼,難以復(fù)用。
3. 充斥著大量入?yún)?,維護(hù)性極低。
4. 等等等等……
原始思路
·?對(duì)于渠道路由于后期肯定是需要有很多可變因素,步驟的, 所以需要考慮流程可編排 便于后期動(dòng)態(tài)調(diào)整。
·?流程可控后為保證數(shù)據(jù)隨時(shí)可用,可傳遞考慮 控制流與數(shù)據(jù)流分離原則。
·?結(jié)合路由領(lǐng)域來(lái)說(shuō),需要實(shí)現(xiàn) 過(guò)濾、規(guī)則執(zhí)行 等特殊功能組件。考慮PipeLine管道模式 進(jìn)行實(shí)現(xiàn)。·?
·?具體領(lǐng)域邏輯中有: 不同PaymentMethod、 不同版本setting數(shù)據(jù)等都會(huì)綜合影響整個(gè)渠道過(guò)濾流程,考量因素差異性比較大,考慮不同代碼實(shí)體實(shí)現(xiàn)主要變化點(diǎn)邏輯隔離 。

演化歷程
以下總結(jié)了一下重構(gòu)的整個(gè)的思考過(guò)程。
· 按照之前原始思路定好了主要組件與設(shè)計(jì)框架開(kāi)發(fā)。 →
·?后來(lái)發(fā)現(xiàn)setting的不同version與不同paymentMethod都可以影響Rules的組合與邏輯?!?
·?Pm、Version、Rule三者存在共同影響。
????a. 代碼硬隔離實(shí)現(xiàn),靈活度低,復(fù)雜度會(huì)高,需要新增許多類但執(zhí)行效率可控。
????b. 通過(guò)反射實(shí)現(xiàn),靈活度高,復(fù)雜度也高,但執(zhí)行效率偏低。
·?有木有一種方法既可以實(shí)現(xiàn)高靈活度的自定義又不需要用反射呢? →
·?組件、流程元數(shù)據(jù)配置化 + Spring Ioc + 無(wú)狀態(tài)組件 + 數(shù)據(jù)context流實(shí)現(xiàn)插件式開(kāi)發(fā)。 →
·?實(shí)現(xiàn)后發(fā)現(xiàn)SettingFilter中要體現(xiàn)version概念,又不想有version邏輯判斷與不同version的Pipe嵌入主流程?!?
·?想到用Strategy模式注入VersionalSettingService,讓其自感知版本并處理過(guò)濾SettingDimension邏輯。 →
·?為了組織Dimension在一起避免太多類,需要統(tǒng)一Dimension接口,考慮Enum組織SettingDimension。 →
·?分析發(fā)現(xiàn)原來(lái)考慮的每個(gè)Dimension需要統(tǒng)一的XXXDimensionSetting對(duì)象結(jié)果用于切面邏輯。Version需要VersionSettingResolver去處理不同version的setting到XXXDimensionSetting的適配邏輯。? →
·?初期感覺(jué)代碼復(fù)雜度與空間復(fù)雜度過(guò)高,且不確定未來(lái)情況下統(tǒng)一的XXXDimensionSetting對(duì)象是否可滿足要求。 怎么辦? →
·?進(jìn)行爭(zhēng)議選項(xiàng)分析,具體見(jiàn)下節(jié)。綜合考慮選擇:移動(dòng)計(jì)算到數(shù)據(jù)的模式。考慮不同version數(shù)據(jù)維持在一個(gè)結(jié)構(gòu)中,讓計(jì)算邏輯XXXDimension在統(tǒng)一version的結(jié)構(gòu)中被運(yùn)用。 →
·?則SetttingDimensionEnum也可以分不同version的Dimension。 →
·?在發(fā)現(xiàn)不同version的DimensionEnum中處理有些公共邏輯,再用composite方式注入公共Dimension Strategy類 →
·?后發(fā)現(xiàn)有不同version的Resonpon邏輯要處理,抽象出VersionalResponseBuilder供調(diào)用 →
·?為了簡(jiǎn)化依賴,統(tǒng)一用VersionalSettingService處理,其代理VersionalResonseBuilder邏輯。利用Kotlin委托實(shí)現(xiàn)Adaptor模式
最后細(xì)化細(xì)節(jié),譬如日志,緩存等。
爭(zhēng)議選型:
設(shè)計(jì)選型:
a方案: 以SettingDimension為主,新建settingObject與不同version的VersionResolver適配Dimension方法進(jìn)行過(guò)濾,讓數(shù)據(jù)適配邏輯。? 單獨(dú)SettingDimension,單獨(dú)VersionResolver,單獨(dú)SettingObject。
b方案: 以versionSetting為主,不同的VersionalSetting對(duì)應(yīng)于多個(gè)SettingDimension方法,不轉(zhuǎn)換對(duì)象,讓versionSetting結(jié)構(gòu)邏輯內(nèi)化到自身,讓邏輯適配數(shù)據(jù)。



時(shí)間復(fù)雜度之爭(zhēng):
時(shí)間復(fù)雜度基本與以前相同
空間復(fù)雜度之戰(zhàn):
移動(dòng)計(jì)算到數(shù)據(jù)設(shè)計(jì)vs移動(dòng)數(shù)據(jù)到計(jì)算設(shè)計(jì)
結(jié)論: 同樣策略模式-> 數(shù)據(jù)具體封閉在一起去除多余轉(zhuǎn)換與轉(zhuǎn)移,比較靈活可控。 計(jì)算策略移動(dòng)到數(shù)據(jù)源去處理某些情況下前者更小空間復(fù)雜度,更靈活
d: 過(guò)濾維度? ? v: setting版本? p: 渠道數(shù)量
空間復(fù)雜度:m+v=o(n)vs? mv=o(n2)
譬如:數(shù)據(jù)有n個(gè)版本data,計(jì)算有m種strategy
data: 分為 d_v1,d_v2 ...., d_vn? ? ? ? ? ? strategy: 分為 s_1, s_1, ... s_m
目的基本就是:找到對(duì)應(yīng)策略執(zhí)行各種版本數(shù)據(jù)
方式一:if 移動(dòng)數(shù)據(jù)到計(jì)算的方式, 這么設(shè)計(jì):? ? strategy.process(common data) 。某些情況下,需要定義一個(gè)針對(duì)此strategy的common data,用于具體strategy 處理此common data結(jié)構(gòu)
方式二:if 移動(dòng)計(jì)算到數(shù)據(jù)的方式, 這么設(shè)計(jì):? ? data.processBy(strategy)? 此種情況下,數(shù)據(jù)具體封閉在data 類中,比較靈活可控。 計(jì)算策略移動(dòng)到數(shù)據(jù)源去處理
實(shí)現(xiàn)步驟:
1. 定好基調(diào):
2. 快速實(shí)現(xiàn)框架流程:
3. 填入細(xì)節(jié):
4. 細(xì)節(jié)方案選型:
5. 評(píng)審與驗(yàn)證方案
6. 實(shí)施方案并反復(fù)修改推演
7. 修繕細(xì)節(jié):優(yōu)化日志,緩存,錯(cuò)誤處理等細(xì)節(jié)。
8. 測(cè)試與細(xì)節(jié)再修繕:
最終結(jié)構(gòu)

Configer: 配置管理器,管理核心配置的獲取,
????包含 Pipe, Rule, Filter, Dimension, PaymentMethod, Version等編排元素的配置獲取。
Pipe: 支持動(dòng)態(tài)編排的管道系統(tǒng)。通過(guò)Configer獲取Pipe配置動(dòng)態(tài)編排管道流程。
????DataAssemblerPipe:查詢setting數(shù)據(jù),pipe line 數(shù)據(jù)裝配準(zhǔn)備。
????RulePipe:根據(jù)rule規(guī)則執(zhí)行rule邏輯。
????DecisionPipe:實(shí)現(xiàn)決策最終pmp的邏輯。
Rule: 支持動(dòng)態(tài)編碼的Rule規(guī)則。通過(guò)Configer獲取Rule配置動(dòng)態(tài)編排管道流程。
????FiltersRule:支持過(guò)濾邏輯的規(guī)則。
????TransactionData Rule,RiskControlRule:暫未實(shí)現(xiàn)。
Filter: 支持動(dòng)態(tài)編碼的Filter。通過(guò)Configer獲取Filter配置動(dòng)態(tài)編排管道流程。
????SettingFilter:組織執(zhí)行版本化的setting的過(guò)濾。
????ProbabilityFilter:根據(jù)概率邏輯執(zhí)行過(guò)濾。
VersionalSettingService: 支持版本化的setting服務(wù)。 通過(guò)Configer獲取Dimension配置動(dòng)態(tài)編排SettingDimension執(zhí)行流程。
????AssembleDimension:組織dimension流程。
????Execute:執(zhí)行Dimension并過(guò)濾pmp。
????VersionalResonpseBuilderHolder:委托相應(yīng)version的ResponseBuilder執(zhí)行buildResponse邏輯。
VersionalSettingDimension: 支持版本化的setting匹配維度
????組織各個(gè)版本的不同dimension數(shù)據(jù),并調(diào)用DimensionStrategy匹配共有dimension邏輯。
實(shí)現(xiàn)
DimensionStrategy: setting維度匹配策略,校驗(yàn)相關(guān)setting中相應(yīng)內(nèi)容是否匹配。
????包含PaymentMethod,Region,TransactionCcy等策略
VersionalResponseBuilder:? 支持版本化的返回?cái)?shù)據(jù)構(gòu)建器
SettingModel:? 具體setting領(lǐng)域?qū)ο?/b>
最終效果:
廢話不多說(shuō),上圖吧:


基本每個(gè)類代碼不超過(guò)200行,各個(gè)組件按照意圖分離,流程控制可配置化
總結(jié)
· 實(shí)現(xiàn) Rules 規(guī)則組件統(tǒng)一控制各種規(guī)則執(zhí)行。
·?實(shí)現(xiàn)Filters 過(guò)濾器組件統(tǒng)一控制轉(zhuǎn)發(fā)與短路。
·?流程元數(shù)據(jù)配置化。通過(guò)組合維度可以靈活控制主要流程。
·?規(guī)則配置化。利于插件式開(kāi)發(fā)。
·?不同版本setting數(shù)據(jù)的一些共有邏輯內(nèi)置化到充血領(lǐng)域模型,便于復(fù)用。
重構(gòu)心得
·? 類比service mesh領(lǐng)域: 控制平面與數(shù)據(jù)平面分離
·? 類比大數(shù)據(jù)、邊緣計(jì)算領(lǐng)域: 移動(dòng)計(jì)算邏輯到數(shù)據(jù)的設(shè)計(jì)方法 (某些情況下可提升靈活性、減少空間復(fù)雜度)
·? 漸進(jìn)性設(shè)計(jì):重構(gòu)一些,多想備選方案,綜合比對(duì)后優(yōu)化
·? 架構(gòu)分析方法論: 設(shè)計(jì) → 編碼-> 難點(diǎn)方案進(jìn)行多維度選型 → 重設(shè)計(jì)與編碼 → 評(píng)估 → 再循環(huán)
未來(lái)展望:
routing service規(guī)劃:
????1. 統(tǒng)一setting獲取邏輯
????2. 加入更多日志
????3. 實(shí)現(xiàn)decision決策邏輯
????4. 實(shí)現(xiàn)配置運(yùn)行時(shí)可編排
????5. setting調(diào)用并行
????6. 基于版本號(hào)的配置推拉機(jī)制
????7. 考慮多filter并行處理
基礎(chǔ)PipeLine庫(kù)規(guī)劃:
????1. PipeContext中支持通過(guò)配置自編排
????2. Pipe支持DSL編排
????3. Pipe支持版本化
????4. Pipe支持異步邏輯
????5. Pipe支持fork-join邏輯
????6. Pipe支持背壓緩沖機(jī)制
插件式開(kāi)發(fā)規(guī)劃與設(shè)計(jì)
通過(guò)合理的設(shè)計(jì),讓配置元數(shù)據(jù)的修改可動(dòng)態(tài)下推到客戶端并解釋執(zhí)行,無(wú)需修改服務(wù)端代碼。 通過(guò)統(tǒng)一的控制平臺(tái)管理執(zhí)行規(guī)則,實(shí)現(xiàn) 控制平面 + 數(shù)據(jù)平面 分離。
1. execute client端
springboot插件:
????a. rule本地存儲(chǔ)(或本地文件等存儲(chǔ)):rule存儲(chǔ)(記錄具體rule規(guī)則,rule執(zhí)行代碼),rule agent存儲(chǔ)(代理具體信息入端口地址等),rule strategy存儲(chǔ)(記錄rule執(zhí)行策略,如是否開(kāi)啟本地執(zhí)行開(kāi)關(guān),降級(jí),熔斷,重試,指標(biāo)等)
????b. 注冊(cè)rules 代碼編譯加載器(啟動(dòng)時(shí),運(yùn)行時(shí)執(zhí)行)
????c. 注冊(cè)代碼執(zhí)行器 -> 反射執(zhí)行rules代碼
????d. 注冊(cè)rule message(包含rule代碼)controller端口,接受信息
????e. 啟動(dòng)rule job(比對(duì)本地存儲(chǔ)版本與最新版本,如果舊了,拉取最新rules并執(zhí)行編譯加載邏輯;如果遠(yuǎn)程服務(wù)不可用,暫停本地執(zhí)行邏輯,快速報(bào)錯(cuò)并開(kāi)啟斷路器)
????f. 斷路器
????g. 遠(yuǎn)程執(zhí)行代理(根據(jù)rule message信息加載遠(yuǎn)程代理),當(dāng)選擇遠(yuǎn)程執(zhí)行時(shí)自動(dòng)遠(yuǎn)程調(diào)用
????h. 提供本地rule執(zhí)行入口方法
2. execute service:
????a. 提供rule存儲(chǔ)服務(wù)
????b. 提供安全認(rèn)證服務(wù)
????c. 提供rule message發(fā)送消息中間件服務(wù)
????d. 提供rule message發(fā)送配置中心推送
3. 通用安全的配置下發(fā)協(xié)議:
????前期可考慮http實(shí)現(xiàn)簡(jiǎn)單
4. msg載體中間件
????a. 中轉(zhuǎn)消息