前幾天一個(gè)事情吵吵好幾天,其實(shí)說(shuō)簡(jiǎn)單也簡(jiǎn)單,不過(guò)各自站的角度不同,也有對(duì)對(duì)方實(shí)現(xiàn)的不理解。
起因
起因是,端上要實(shí)現(xiàn)一個(gè)周期性啟動(dòng)的任務(wù),最終決定由服務(wù)端來(lái)調(diào)度啟動(dòng)。因?yàn)橐恍v史原因,原先的啟動(dòng)是通過(guò)修改一個(gè)云控配置來(lái)實(shí)現(xiàn)。所以就期望服務(wù)端調(diào)度啟動(dòng)的時(shí)候,也是通過(guò)下發(fā)一個(gè)同樣的配置(不是簡(jiǎn)單的信息,是比較復(fù)雜的yaml文件)來(lái)實(shí)現(xiàn)。由于當(dāng)時(shí)沒(méi)考慮太多,就同意了這種實(shí)現(xiàn)方式,于是就埋了一個(gè)坑。
后續(xù)就是正常功能開發(fā),上線。
問(wèn)題
上線后發(fā)現(xiàn)這個(gè)任務(wù)想要運(yùn)行起來(lái),還需要開啟一個(gè)端上的配置開關(guān)才能運(yùn)行,所以在每次調(diào)度啟動(dòng)的時(shí)候還需要同步下發(fā)一個(gè)開關(guān)配置。也就是說(shuō)服務(wù)想要調(diào)度這個(gè)功能運(yùn)行需要下發(fā)兩個(gè)信息(開關(guān)+調(diào)度配置)。
其實(shí)在做這個(gè)的時(shí)候我也知道有這個(gè)開關(guān),本來(lái)是想在功能上線之后,配置一個(gè)對(duì)全量設(shè)備生效的開關(guān)就 OK,但后來(lái)發(fā)現(xiàn)遠(yuǎn)沒(méi)有這么容易。
首先這個(gè)開關(guān)開啟后,端上將自動(dòng)啟動(dòng)一次任務(wù)。那么如果全量開啟,意味著所有設(shè)備將在同時(shí)啟動(dòng)這個(gè)任務(wù)。但業(yè)務(wù)方對(duì)這個(gè)狀態(tài)是無(wú)法接受的。認(rèn)為這是一個(gè)支線任務(wù),只能均勻的調(diào)度啟動(dòng)(最多只能有 1/7 的設(shè)備同時(shí)啟動(dòng)),而不能一下都啟動(dòng),導(dǎo)致主線任務(wù)無(wú)法進(jìn)行(無(wú)法回傳核心數(shù)據(jù))。但其實(shí)就算均勻啟動(dòng),在一個(gè)運(yùn)行周期內(nèi)做這任務(wù)的用的總時(shí)間是一樣的。
其次端上在使用這個(gè)配置的時(shí)候,會(huì)跟本地已經(jīng)存在的配置做一個(gè) merge。這意味著每個(gè)設(shè)備上的這個(gè)配置內(nèi)容都可能不同,所以就不能簡(jiǎn)單的下一個(gè)全局的配置,而是要先讀取端上正在使用的配置,將這個(gè)配置中的啟動(dòng)開關(guān)打開之后再下發(fā)到端上。
接著就是好幾輪的掰扯了。
端上希望服務(wù)下兩個(gè)配置:開關(guān)+調(diào)度配置,在每次調(diào)度前先檢測(cè)下開關(guān)是否關(guān)閉,如果關(guān)閉狀態(tài),需要先下發(fā)一個(gè)配置將其打開,而后再下發(fā)調(diào)度配置。
而服務(wù)這一直堅(jiān)持:只下發(fā)調(diào)度配置,開關(guān)不應(yīng)由服務(wù)控制。
服務(wù)為什么堅(jiān)持呢?原因主要有三個(gè)。
- 遵循高內(nèi)聚低耦合的思想,模塊之間的交互就是應(yīng)該做到最簡(jiǎn)單。其實(shí)最合理的方案也不是這樣。服務(wù)本不應(yīng)該下發(fā)復(fù)雜的 yaml 配置文件,而應(yīng)該只下發(fā)一個(gè)任務(wù)啟動(dòng)的信號(hào)(也就是前面說(shuō)過(guò)埋的坑)
- 這個(gè)存在的開關(guān)意味著有手動(dòng)開關(guān)的需求,如果服務(wù)調(diào)度之前就啟動(dòng)下,那跟沒(méi)有有什么區(qū)別?如果調(diào)度貿(mào)然改了手動(dòng)下發(fā)的配置,有可能會(huì)產(chǎn)生業(yè)務(wù)問(wèn)題。調(diào)度不應(yīng)該去干預(yù)業(yè)務(wù)內(nèi)部的控制邏輯。
- 只下發(fā)配置,意味著更少的代碼量,更少的數(shù)據(jù)庫(kù)記錄數(shù),如果能用更少的代碼,更少的數(shù)據(jù)量來(lái)實(shí)現(xiàn)一樣的功能,為什么不呢?
解決
但最后還是誰(shuí)也沒(méi)說(shuō)服誰(shuí),問(wèn)題上升了,由老板組了個(gè)場(chǎng)子又扯了一遍。
最終的解決方式是:
在灰度驗(yàn)證完之后,將啟動(dòng)全量調(diào)度,端上的調(diào)度開關(guān)后續(xù)會(huì)默認(rèn)打開(在端上存在的默認(rèn)配置會(huì)改為打開)。
- 在端上開關(guān)默認(rèn)打開之前,由服務(wù)下發(fā):開關(guān)+調(diào)度配置
- 在端上開關(guān)默認(rèn)打開之后,服務(wù)只下發(fā):調(diào)度配置
于是我將打開開關(guān)的操作,單獨(dú)拆了一個(gè)調(diào)度任務(wù)出來(lái)。這樣就可以在不改變?cè)写a的前提下,也可以滿足端上任務(wù)啟動(dòng)的目的。在全量之后,直接把這個(gè)調(diào)度任務(wù)關(guān)閉就可以了。
感想
整個(gè)事情之后,我想了下,為什么要弄的這么復(fù)雜?
其實(shí)最開始的時(shí)候,如果能堅(jiān)持使用發(fā)送信號(hào)的方式,就沒(méi)有后續(xù)這些事情了,而當(dāng)時(shí)的妥協(xié)導(dǎo)致了后續(xù)的爭(zhēng)論。所以這個(gè)也告誡我,要堅(jiān)持做對(duì)的事情,不能因?yàn)榉N種原因妥協(xié)。前期的妥協(xié)可能帶來(lái)巨大的坑,后期爭(zhēng)論帶來(lái)的負(fù)面反饋絕對(duì)比前期妥協(xié)帶來(lái)的正面反饋要多的多。同時(shí)也看到,系統(tǒng)與系統(tǒng)、端與端、模塊與模塊之間的交互就是要做到信息傳遞的最小化,千萬(wàn)不要去控制其他模塊的內(nèi)部邏輯。
其實(shí),中間我也幾次想要妥協(xié),因?yàn)榘凑漳欠N方式也可以實(shí)現(xiàn)。但做事情永遠(yuǎn)是:由該不該做決定,而不是能不能做。程序?qū)π枨蟮膶?shí)現(xiàn)能有很多種,但最優(yōu)的只有那一種。就像對(duì) 2 這數(shù)字來(lái)說(shuō),1 << 1 = 2;1 + 1 = 2;99999 - 99997 = 2;這三種實(shí)現(xiàn),哪個(gè)對(duì)計(jì)算機(jī)的計(jì)算成本最低呢?最近看了幾個(gè)機(jī)器學(xué)習(xí)的視頻,對(duì)一個(gè)模型的評(píng)價(jià)會(huì)使用 Loss 函數(shù),其實(shí)我們?cè)谠u(píng)價(jià)需求實(shí)現(xiàn)的時(shí)候,也是需要有個(gè)自己的 Loss 函數(shù)。