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