一位老極客的眼中的開發和部署
多年前,我曾是一名 Smalltalk 程序員,這種經驗讓我以一種不同的視角來觀察編程的世界,例如,需要花時間來適應源代碼應該存儲在文本文件中的這種做法。
我們作為程序員通常會區分「開發」和「部署」,特別是我們在開發的地方所使用的工具不同於我們在之後部署軟體時的地點和工具時。而在 Smalltalk 世界裡,沒有這樣的區別。
Smalltalk 構建於虛擬機包含了你的開發環境(IDE、調試器、文本編輯器、版本控制等)的思路之上,如果你需要修改任何一處代碼,你得修改內存中運行副本。如果需要的話,你可以為運行中的機器做個快照;如果你想分發你的代碼,你可以發送一個運行中的機器的鏡像副本(包括 IDE、調試器、文本編輯器、版本控制等)給用戶。這就是上世紀 90 年代軟體開發的方式(對我們中的一些人來說)。
如今,部署環境與開發環境有了很大的不同。起初,你不要期望那裡(指部署環境)有任何開發工具。一旦部署,就沒有版本控制、沒有調試、沒有開發環境。有的是記錄和監視,這些在我們的開發環境中都沒有,而有一個「構建管道」,它將我們的軟體從開發形式轉換為部署形式。作為一個例證,Docker 容器則試圖重新找回上世紀 90 年代 Smalltalk 程序員部署體驗的那種簡單性,而避免同樣的開發體驗。
我想如果 Smalltalk 世界是我唯一的編程方面的體驗,讓我無法區分開發和部署環境,我可能會偶爾回顧一下它。但是在我成為一名 Smalltalk 程序員之前,我還是一位 APL 程序員,這也是一個可修改的虛擬機鏡像的世界,其中開發和部署是無法區分的。因此,我相信,在當前的時代,人們編輯單獨的源代碼文件,然後運行構建管道以創建在編輯代碼時尚不存在的部署作品,然後將這些作品部署給用戶。我們已經以某種方式將這種反模式的軟體開發制度化,而不斷發展的軟體環境的需求正在迫使我們找回到上世紀 90 年代的更有效的技術方法。因此才會有 Docker 的成功,所以,我需要提出我的建議。
我有兩個建議:我們在運行時系統中實現(並使用)版本控制,以及,我們通過更改運行中的系統來開發軟體,而不是用新的運行系統替換它們。這兩個想法是相關的。為了安全地更改正在運行的系統,我們需要一些版本控制功能來支持「撤消」功能。也許公平地說,我只提出了一個建議。讓我舉例來說明。
讓我們開始假設一個靜態網站。你要修改一些 HTML 文件。你應該如何工作?如果你像大多數開發者一樣,你會有兩個,也許三個網站 - 一個用於開發,一個用於 QA(或者預發布),一個用於生產。你將直接編輯開發實例中的文件。準備就緒後,你將把你的修改「部署」到預發布實例。在用戶驗收測試之後,你將再次部署,這次是生產環境。
使用 Occam 的 Razor,讓我們可以避免不必要地創建實例。我們需要多少台機器?我們可以使用一台電腦。我們需要多少台 web 伺服器?我們可以使用具有多個虛擬主機的單台 web 伺服器。如果不使用多個虛擬主機的話,我們可以只使用單個虛擬主機嗎?那麼我們就需要多個目錄,並需要使用 URL 的頂級路徑來區分不同的版本,而不是虛擬主機名。但是為什麼我們需要多個目錄?因為 web 伺服器將從文件系統中提供靜態文件。我們的問題是,目錄有三個不同的版本,我們的解決方案是創建目錄的三個不同的副本。這不是正是 Subversion 和 Git 這樣的版本控制系統解決的問題嗎?製作目錄的多個副本以存儲多個版本的策略回到了版本控制 CVS 之前的日子。為什麼不使用比如說一個空的的 Git 倉庫來存儲文件呢?要這樣做,web 伺服器將需要能夠從 git 倉庫讀取文件(參見 mod_git)。
這將是一個支持版本控制的運行時系統。
使用這樣的 web 伺服器,使用的版本可以由 cookie 來標識。這樣,任何人都可以推送到倉庫,用戶將繼續看到他們發起會話時所分配的版本。版本控制系統有不可改變的提交; 一旦會話開始,開發人員可以在不影響正在運行的用戶的情況下快速推送更改。開發人員可以重置其會話以跟蹤他們的新提交,因此開發人員或測試人員就可能如普通用戶一樣查看在同台伺服器上同一個 URL 上正在開發或正在測試的版本。作為偶然的副作用,A/B 測試僅僅是將不同的用戶分配給不同的提交的情況。所有用於管理多個版本的 git 設施都可以在運行環境中發揮作用。當然,git reset 為我們提供了前面提到的「撤銷」功能。
為什麼不是每個人都這樣做?
一種可能性是,諸如版本控制系統的工具沒有被設計為在生產環境中使用。例如,給某人推送到測試分支而不是生產分支的許可是不可能的。對這個方案最常見的反對是,如果發現了一個漏洞,你會想要將某些提交標記為不可訪問。這將是另一種更細粒度的許可權的情況;開發人員將具有對所有提交的讀取許可權,但外部用戶不會。我們可能需要對現有工具進行一些額外的改造以支持這種模式,但是這些功能很容易理解,並已被設計到其他軟體中。例如,Linux (或 PostgreSQL)實現了對不同用戶的細粒度許可權的想法。
隨著雲環境變得越來越普及,這些想法變得更加相關:雲總是在運行。例如,我們可以看到,AWS 中等價的 「文件系統」(S3)實現了版本控制,所以你可能有一個不同的想法,使用一台 web 伺服器提供來自 S3 的資源文件,並根據會話信息選擇不同版本的資源文件。重要的並不是哪個實現是最好的,而是支持這種運行時版本控制的願景。
部署的軟體環境應該是「版本感知」的原則,應該擴展到除了服務靜態文件的 web 伺服器之外的其他工具。在將來的文章中,我將介紹版本庫,資料庫和應用程序伺服器的方法。
作者簡介:
Robert M. Lefkowitz - Robert(即 r0ml)是一個喜歡複雜編程語言的編程語言愛好者。 他是一個提高清晰度、提高可靠性和最大限度地簡化的編程技術收藏家。他通過讓計算機更加容易獲得來使它普及化。他經常演講中世紀晚期和早期文藝復興對編程藝術的影響。
via: The difference between development and deployment
作者:Robert M. Lefkowitz 譯者:geekpi 校對:Bestony
本文由 LCTT 原創編譯,Linux中國 榮譽推出
推薦閱讀: