創(chuàng)新互聯(lián)建站是一家專業(yè)從事網(wǎng)站制作、成都網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)的品牌網(wǎng)絡(luò)公司。如今是成都地區(qū)具影響力的網(wǎng)站設(shè)計(jì)公司,作為專業(yè)的成都網(wǎng)站建設(shè)公司,創(chuàng)新互聯(lián)建站依托強(qiáng)大的技術(shù)實(shí)力、以及多年的網(wǎng)站運(yùn)營(yíng)經(jīng)驗(yàn),為您提供專業(yè)的成都網(wǎng)站建設(shè)、營(yíng)銷型網(wǎng)站建設(shè)及網(wǎng)站設(shè)計(jì)開(kāi)發(fā)服務(wù)!
在社區(qū)的支持下,PouchContainer 已有超過(guò) 2700 個(gè) commit,100 多位社區(qū)開(kāi)發(fā)者的踴躍貢獻(xiàn),其中不乏國(guó)內(nèi)一線互聯(lián)網(wǎng)公司、容器明星創(chuàng)業(yè)公司貢獻(xiàn)者的參與。
想了解更多 PouchContainer 的同學(xué)可以點(diǎn)擊這篇了解上下文: PouchContainer 富容器技術(shù)
為什么要做內(nèi)外版本一致
一般開(kāi)源產(chǎn)品在對(duì)外開(kāi)源的過(guò)程中,首先是將可以開(kāi)源的部分抽離出來(lái),發(fā)布一個(gè)“開(kāi)源版本”,與內(nèi)部基礎(chǔ)設(shè)施相關(guān)的部分則留在內(nèi)部版本中。在后續(xù)的開(kāi)發(fā)中,開(kāi)源版本隨著社區(qū)不斷演進(jìn),內(nèi)部版本則隨著內(nèi)部的需求不斷迭代。如果沒(méi)有明確定義內(nèi)外部版本的邊界、代碼同步不完全、不及時(shí),將會(huì)導(dǎo)致內(nèi)外版本越走越遠(yuǎn),變成兩個(gè)不相干的項(xiàng)目。
促使我們開(kāi)始做內(nèi)外版本一致事情的,主要是以下三點(diǎn)考慮:
降低維護(hù)成本:這也是同步工作的出發(fā)點(diǎn)。減少多版本維護(hù)的工作負(fù)擔(dān),也方便團(tuán)隊(duì)的交流。
發(fā)揮社區(qū)的優(yōu)勢(shì):吸收社區(qū)力量是開(kāi)源的一個(gè)重要考慮,讓社區(qū)的力量真正在內(nèi)部發(fā)揮價(jià)值。社區(qū)會(huì)有一些我們沒(méi)有考慮到的需求,有集結(jié)社區(qū)力量的更嚴(yán)格的 review,與 github 集成的強(qiáng)約束 CI 等。
降低功能同步的風(fēng)險(xiǎn):在內(nèi)外部版本不同源的情況下,將外部代碼合并進(jìn)來(lái)非常容易沖突。代碼模塊較多,解決沖突的過(guò)程中,一不小心就會(huì)引入非預(yù)期的修改,而這在合并的過(guò)程中,很難發(fā)現(xiàn)。
本文將詳細(xì)說(shuō)明 PouchContainer 是如何做到內(nèi)外部版本一致的。
差異梳理及邊界定義
PouchContainer 開(kāi)源已經(jīng)將近一年了,在內(nèi)外部版本差異梳理之前,沒(méi)有人能講清楚兩個(gè)版本之間的差異。于是我用 Beyond Compare4 等軟件,進(jìn)行文件級(jí)別的比對(duì),一個(gè)個(gè)找出內(nèi)外部不同的代碼,進(jìn)而梳理出內(nèi)外部功能級(jí)別的差異。所幸內(nèi)外部的差異比我想象中的要小。主要有以下幾類差異:
對(duì)內(nèi)部老系統(tǒng)的接口兼容
為內(nèi)部系統(tǒng)開(kāi)的后門接口
對(duì)接內(nèi)部基礎(chǔ)設(shè)施的邏輯,如存儲(chǔ),網(wǎng)絡(luò)
bugfix, feature 沒(méi)有互相同步
前三類差異是集團(tuán)內(nèi)針對(duì) PouchContainer 的定制化內(nèi)容。當(dāng)然,有一些是目前迫不得已加上的臨時(shí)邏輯。在后續(xù)的發(fā)展中,將會(huì)改造、下線。第四類的差異,主要原因在于開(kāi)發(fā)者沒(méi)有版本同步的意識(shí):bugfix 在內(nèi)部緊急修復(fù)之后,沒(méi)有同步到社區(qū)。社區(qū)開(kāi)發(fā)者的 bugfix, feature 沒(méi)有及時(shí)同步進(jìn)內(nèi)部代碼。
在差異梳理出來(lái)之后,需要明確內(nèi)外部的功能邊界。能開(kāi)源的就開(kāi)源,獨(dú)有的功能繼續(xù)保留。抹平非功能性的不一致。
一致性改造
版本同步的根本還是提升軟件的可拓展性,允許共用一套核心代碼,針對(duì)不同的業(yè)務(wù)場(chǎng)景進(jìn)行定制。所以我們面對(duì)的問(wèn)題不僅是內(nèi)外部版本的一致問(wèn)題,應(yīng)該是三版本、四版本、多版本的一致問(wèn)題。這也是 PouchContainer 賦能其他業(yè)務(wù)場(chǎng)景的基礎(chǔ)。同樣也是開(kāi)源項(xiàng)目?jī)?nèi)部使用的必修課所以,我們做的第二步是通過(guò)插件機(jī)制提升 PouchContainer 的可拓展性。目前我們支持 API, container, daemon, volume,cri 這五種插件。具體見(jiàn)文檔。
插件的設(shè)計(jì)旨在提升軟件的擴(kuò)展性,但不允許插件改變?cè)械墓ぷ髁鞒?。PouchContainer 提供了對(duì) container, daemon, volume, cri 關(guān)鍵步驟的 hook。以 daemon 插件為例,該插件提供了對(duì)啟停接口的 hook。插件實(shí)現(xiàn)者可以在 daemon 啟動(dòng)前運(yùn)行一些其他程序,比如 dfget。在 daemon 停止前,做一些清理操作。
// DaemonPlugin defines places where a plugin will be triggered in pouchd lifecycle
type DaemonPlugin interface {
// PreStartHook is invoked by pouch daemon before real start, in this hook user could start dfget proxy or other
// standalone process plugins
PreStartHook() error
// PreStopHook is invoked by pouch daemon before daemon process exit, not a promise if daemon is killed, in this
// hook user could stop the process or plugin started by PreStartHook
PreStopHook() error
}
而 API 插件通過(guò)將路由表傳給插件,允許插件實(shí)現(xiàn)者擴(kuò)展、刪除、修改 API。這讓接口有了很大的靈活性。
import "github.com/alibaba/pouch/apis/server/types"
// APIPlugin provide the ability to extend PouchContainer HTTP API and change how handler behave.
type APIPlugin interface {
// The default handler of each API would be passed in while starting HTTP server.
// UpdateHandler could register extra HTTP API to PouchContainer server,
// change the behavior of the default handler.
UpdateHandler([]*types.HandlerSpec) []*types.HandlerSpec
}
通過(guò)插件化的改造,絕大部分的內(nèi)部 PouchContainer 定制化邏輯都在插件中實(shí)現(xiàn)了。插件單獨(dú)一個(gè)文件目錄,在代碼合入的時(shí)候幾乎不會(huì)產(chǎn)生沖突。之后將內(nèi)部插件邏輯和其他差異一個(gè)個(gè) commit 到開(kāi)源分支上。做到內(nèi)外部版本的同源。
穩(wěn)定性保障
PouchContainer 開(kāi)源版本代表通用功能,如果外部開(kāi)發(fā)者在通用版本上迭代的新增功能,集團(tuán)內(nèi)部用不到,該如何保障外部功能同步到內(nèi)部之后,不影響內(nèi)部的現(xiàn)有功能的?
首先內(nèi)部版本是有一套完整的測(cè)試覆蓋的,內(nèi)部測(cè)試在開(kāi)源測(cè)試的基礎(chǔ)上還包含針對(duì)內(nèi)部場(chǎng)景的測(cè)試。內(nèi)部測(cè)試通過(guò),我們便認(rèn)為該版本是符合內(nèi)部場(chǎng)景要求的,開(kāi)源版本沒(méi)有影響內(nèi)部穩(wěn)定性的。如果測(cè)試不通過(guò),有兩個(gè)選擇,一是重新評(píng)估開(kāi)源通用功能,是否有代碼缺陷;二是在內(nèi)部倉(cāng)庫(kù)打補(bǔ)丁。以此來(lái)保障開(kāi)源代碼同步至內(nèi)部后的穩(wěn)定性。
建立新的秩序
我們先來(lái)看看,在這之前的工作流是怎樣的。開(kāi)發(fā)者分別在內(nèi)部倉(cāng)庫(kù)和開(kāi)源倉(cāng)庫(kù)提代碼,緊急一些的需求會(huì)先在內(nèi)部倉(cāng)庫(kù)提 merge request,不那么重要的需求會(huì)先在社區(qū)提 PR。有人會(huì)定期將開(kāi)源分支 merge 進(jìn)內(nèi)部倉(cāng)庫(kù)。這里有幾個(gè)問(wèn)題,一是內(nèi)部也有一套測(cè)試流程,這套流程可能不像 travisCI 或 circleCI 對(duì)接 github 那么方便,有些設(shè)計(jì)好的測(cè)試在內(nèi)部倉(cāng)庫(kù)甚至不會(huì)跑。二是沒(méi)有插件化前,某些功能在內(nèi)外部有兩種不同的實(shí)現(xiàn),這在每次手動(dòng) merge 代碼的時(shí)候幾乎都會(huì)沖突,解決沖突的過(guò)程很容易引入非預(yù)期的修改,下次又繼續(xù)沖突。
git flow 如圖
在完成一致性改造之后,我們建立一套規(guī)則來(lái)保證后續(xù)不會(huì)再出現(xiàn)版本分離的事情。
原則上非私有增強(qiáng),應(yīng)該先在社區(qū)提交 PR,merge 之后通過(guò)同步機(jī)制進(jìn)入內(nèi)部版本
如果時(shí)間緊急,bugfix 先在內(nèi)部版本上提交。后續(xù) commiter 負(fù)責(zé)將其 cherry-pick 到社區(qū)。社區(qū) review 發(fā)現(xiàn)需要繼續(xù)修改的,將修改另提一個(gè) commit,這樣保證 commit 不與內(nèi)部倉(cāng)庫(kù)沖突
代碼同步,由機(jī)器人定時(shí)提交 merge request 將開(kāi)源同步至內(nèi)部
在 merge 的時(shí)候,保證是 fast-forward 的,這樣內(nèi)外部的 commit 是一一對(duì)應(yīng)的,減少?zèng)_突。
總結(jié)
開(kāi)源,能幫助項(xiàng)目吸收外部養(yǎng)分,加速項(xiàng)目的演進(jìn)。在一致性的改造過(guò)程中,幫助開(kāi)發(fā)者明確內(nèi)外部版本的邊界,打造同一份核心代碼,提升核心代碼的可定制化能力,更好地服務(wù)于不同的場(chǎng)景。
網(wǎng)站名稱:PouchContainer開(kāi)源版本及內(nèi)部版本一致性實(shí)踐
網(wǎng)站網(wǎng)址:http://m.rwnh.cn/article44/jejphe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、關(guān)鍵詞優(yōu)化、網(wǎng)站設(shè)計(jì)、外貿(mào)建站、App開(kāi)發(fā)、自適應(yīng)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)