許式偉:架構設計的宏觀視角

本文內容選自《許式偉的架構課》

在信息科技高度發展的今天,我們每個人隨時隨地都可以接觸到由程序驅動的智能電子設備,包括手機(如iPhone、oppo拍照手機)、平板電腦(如iPad)、手錶(如iWatch、小天才智能手錶)、音箱(如天貓精靈)、汽車(如特斯拉)等等。

這些東西背後是怎麼工作的?單就其中的軟件系統而言,這些小小的設備上往往運行着成千上萬個軟件模塊,這些模塊是如何如此精密地一起協作的?

對此,我過去接觸過很多的軟件開發工程師,或者架構師,很多人對這些原理也是一知半解,雖然“知其然”,但卻“不知其所以然”。甚至有些朋友可能覺得,學這些有什麼用處呢,在我看來,這部分內容恰恰是我們成爲架構師很重要的一門基礎課

爲什麼需要建立宏觀視角?

如同造房子有建築工人(負責搬磚)和建築師(負責架構設計)一樣,軟件系統的開發過程同樣需要有程序員(負責搬“磚”)和架構師(負責架構設計)。作爲架構師,我們需要的第一個能力是宏觀的全局掌控能力。

如果把應用程序比作一座大廈,那麼我們作爲大廈的架構師,需要把大廈的結構搭建好,讓程序員可以把磚填充進去,我們都知道,一個大廈的結構建得是否穩固,與地基密不可分。

所以,我們首先就需要從大廈的地基開始,熟悉這座大廈。畢竟,你對所依賴的基礎架構瞭解得越全面,做業務架構設計就會越發從容。

介紹基礎架構的知識點並不是讓你真的去實現它們。但你仍然需要懂得它們的核心思想是什麼,知道有哪些信息是你必須深刻理解的,以便可以更好地駕馭它們。

我們的整個專欄內容也會從基礎架構開始講起,最後逐步過渡到業務架構,到最終完成一個完整應用程序的設計過程。

那麼,在今天的開篇第一篇,我們需要站在宏觀視角,從基礎架構開始,逐漸來解剖一個應用程序的整體構成,我希望,通過今天的文章,可以讓你對於一個程序的全貌,形成完整的認識。

應用程序的基礎架構

我們想學習一個程序的基礎架構,其實就是弄清楚電腦的工作原理,以及程序的運行原理。

無論是什麼樣的智能電子設備,手機也好,汽車也罷,它們都可以稱爲“電腦”。所有的電腦都可以統一看作由中央處理器+存儲+一系列的輸入輸出設備構成。

中央處理器,也就是我們平常說的CPU,負責按指令執行命令;存儲負責保存數據,包括我們要執行的命令,也是以數據形式保存在存儲中的。

每次在打開電腦的電源後,中央處理器都會從存儲的某個固定位置處開始讀入數據(也就是指令),並且按指令執行命令,執行完一條指令就會繼續執行下一條指令。電腦就這樣開始工作了。

你可能會說,就這麼簡單?是的,就是這麼簡單。

那這麼簡單的話,爲何電腦能夠完成這麼多複雜而多樣化的工作?

這整個過程,在我看來主要依賴兩點。

第一是可編程性大體來說,中央處理器(CPU)的指令分爲如下這幾類。

  • 計算類,也就是支持我們大家都熟知的各類數學運算,如加減乘除、sin/cos等等。

  • I/O類,(從存儲讀寫數據)從輸入輸出設備讀數據、寫數據。

  • 指令跳轉類,在滿足特定條件下跳轉到新的當前程序執行位置。

雖然, CPU 指令是一個很有限的指令集,但是CPU 執行的指令序列(或者叫“程序”)並不是固定的,而是依賴保存在存儲中的數據—— 由軟件工程師(或者叫“程序員”)編寫的軟件來決定。指令序列的可能性是無窮的,這也就意味着電腦能夠做的事情的可能性也是無窮的。

第二是開放設計的外部設備支持。雖然我們電腦可以連接非常非常多種類的外部設備,比如鍵盤、打印機、屏幕、汽車馬達等等,但CPU 並不理解這些設備具體有什麼樣的能力,它只和這些設備交換數據。它能夠做的是從某個編號的設備(通常這個設備編號被稱爲“端口”)讀入一段數據,或者向設備的端口寫入一段數據。

例如,當你在鍵盤上按下了A的時候,CPU 可以從鍵盤連接的端口讀到一段數據,通過這段數據來表達你按了“A”,可能CPU 會向打印機連接的端口發送一段數據,來驅動打印機打印特定的文本;還有可能CPU 會向汽車馬達所在的端口發送數據,來驅動馬達轉動,從而讓汽車按照預期來行駛。

值得注意的是,CPU 知道的是如何和這些設備交換數據,但是並不理解數據代表什麼含義。這些外部設備的廠商在提供設備硬件的同時,往往也需要提供和硬件匹配的軟件,來完成和CPU 的協作,讓軟件工程師可以輕鬆使用這些設備。

從上面可以看出,電腦的 CPU 是一個非常簡潔的模型,它只讀入和寫出數據,對數據進行計算。這也是爲什麼我們往往把電腦也叫作“計算機”,這是因爲 CPU 這個計算機的大腦的確只會做“計算”。

這個基礎的設計體系,我們很多人都知道,這就是馮·諾依曼計算機體系。1945年6月,馮·諾依曼以“關於EDVAC的報告草案”爲題起草的長達101頁的總結報告,定義了“馮·諾依曼體系結構”,他現在也被稱爲計算機之父。我想看到這裏,你應該不難理解他的偉大之處了吧?

有了這個基礎的計算機體系之後,我們就可以編寫軟件了。

當然我們遇到的第一個問題是直接用機器指令編寫軟件太累,而且這些機器指令像天書一樣沒人看得懂,沒法維護。

所以,編程語言+編譯器就出現了。編譯器負責把我們人類容易理解的語言,轉換爲機器可以理解的機器指令,這樣一來就大大解放了編寫軟件的門檻。

在編寫軟件不是問題時,我們遇到的第二個問題,就是多個軟件在同一個電腦上怎麼共處。多個軟件大家往同一個存儲地址寫數據衝突怎麼辦?一起往打印機去發送打印指令怎麼辦?有的軟件可能偷偷搞破壞怎麼辦?

於是,操作系統就出現了。

首先要解決的是軟件治理的問題。它要建立安全保護機制,確保你的電腦免受惡意軟件侵害。同時,它也要建立軟件之間的協作秩序,讓大家按照期望的方式進行協作。比如存儲你寫到這裏,那麼我就要寫到別處;使用打印機要排隊,你打完了,我才能接着去打印。

操作系統其次解決的是基礎編程接口問題。這些編程接口一方面簡化了軟件開發,另一方面提供了多軟件共存(多任務)的環境,實現了軟件治理。

例如,對於屏幕設備,操作系統需要提供多任務窗口系統,以避免屏幕被多個軟件畫得亂七八糟;對於鍵盤輸入設備,操作系統引入焦點窗口,以確定鍵盤輸入的事件被正確發送到正確的軟件程序。

你會發現,今天的我們開發軟件的時候,已經處於一些基礎的架構設計之中。像馮·諾依曼計算機體系,像操作系統和編程語言,這些都是我們開發一個應用程序所依賴的基礎架構。

基礎架構解決的是與業務無關的一些通用性的問題,這些問題往往無論你具體要做什麼樣的應用都需要面對。而且,基礎架構通常以獨立的軟件存在,所以也稱爲基礎軟件。

例如,我們熟知的Linux、Nginx、MySQL、PHP 等這些軟件都屬於基礎軟件,這些基礎軟件極大地降低了應用開發的難度。在今天軟件服務化的大趨勢下,很多基礎軟件最終以互聯網服務的方式提供,這就是所謂的“雲計算”。

完整的程序架構是怎樣的?

講完了程序的地基,讓我們來總覽一下程序的完整架構。

在越強大的基礎架構支撐下,應用程序開發需要關注的問題就越收斂,我們的開發效率就越高。在我們只需要關注應用程序本身的業務問題如何構建時,我們說自己是在設計應用程序的業務架構(或者叫“應用架構”)。

業務架構雖然會因爲應用的領域不同而有很大的差異,但不同業務架構之間,仍然會有許多共通的東西。它們不只遵循相同的架構原則,還可以遵循相同的設計範式。

一些設計範式被人們以應用程序框架的方式固化下來。例如,在用戶交互領域有著名的MVC 框架(如JavaScript 語言的Angular,PHP 語言的Zend,Python 語言的 Django),在遊戲開發領域有各種遊戲引擎(如JavaScript 語言的 Phaser,C# 語言的 Unity3D),等等。

對於一個服務端應用程序來說,其完整的架構體系大體如下

對於客戶端應用程序來說,和服務端的情況會有非常大的差別。客戶端首先面臨的是多樣性的挑戰。

單就操作系統來說,PC 就有Windows、Mac、Linux 等數十種,手機也有Android、iOS,Windows Mobile 等等。而設備種類而言就更多了,不只有筆記本、平板電腦,還有手機、手錶、汽車,未來只會更加多樣化。

第一個想消除客戶端的多樣性,並且跨平臺提供統一編程接口的,是瀏覽器。

可能在很多人看來,瀏覽器主要改變的是軟件分發的方式,讓軟件可以即取即用,無需安裝。但從技術角度來說,底層操作系統對軟件的支持同樣可以做到即取即用。

這方面蘋果在iOS 上已經在嘗試,大家可能已經留意到,如果你一個軟件很久沒有用,iPhone 就會把這個軟件從本地清理出去,而在你下一次使用它時又自動安裝回來。假如軟件包足夠小,那麼這種行爲和 Web 應用就毫無區別。不同之處只在於Web 應用基於的指令不是機器碼,而是更高階的 JavaScript 腳本。

JavaScript 因爲指令更高階,所以程序的尺寸比機器碼會有優勢。但另一方面來說 JavaScript 是文本指令,表達效率又要比機器碼低。但這一點也在發生變化,近年來 WebAssembly 技術開始蓬勃發展,JavaScript 作爲瀏覽器的機器碼的地位會被逐步改變,我們前端開發會面臨更多的可能性。

瀏覽器的地位非常特殊,我們可以看作操作系統之上的操作系統。一旦某種瀏覽器流行起來,開發人員都在瀏覽器上做應用,那麼必然會導致底層操作系統管道化,這是操作系統廠商所不願意看到的。

而如果瀏覽器用戶量比較少,那麼通過它能夠觸達的用戶量就太少,消除不同底層操作系統差異的價值就不存在,開發人員也就不樂意在上面開發應用。

我們知道,PC 的瀏覽器之戰打到今天,基本上就剩下Chrome、Internet Explorer、Safari、Firefox 等。有趣的是,移動瀏覽器的戰場似乎是從中國開始打起的,這就是微信引發的小程序之戰,它本質上是一場瀏覽器的戰爭。

瀏覽器是一個基礎軟件,它能夠解決多大的問題,依賴於它的市場佔有率。但是基於同樣的瀏覽器技術核心也可以構建出跨平臺的應用框架。我們看到 React Native 就是沿着這個思路走的。當然這不是唯一的一條路,還有人會基於類似 QT 這樣的傳統跨平臺方案。

整體來說,對於一個客戶端應用程序來說,其完整的架構體系大體如下

對於架構師來說,不僅僅只是想清楚業務應該怎麼去做好分解,整個應用從底到最頂層的上層建築,每一層都需要進行各種決策。先做 iOS 版本,還是先做小程序?是選擇 Java 還是 Go 語言?這些都是架構的一部分。

結語

今天,我們從“計算機是如何工作”開始,一起登高鳥瞰,總覽了程序完整的架構體系。

可能有人看到今天的內容心裏會有些擔心:“原來架構師要學這麼多東西,看來我離成爲架構師好遠。”

好消息是:我們就是來打消這個擔心的。如果我們把寫代碼的能力比作武功招式,那麼架構能力就好比內功。內功修煉好了,武功招式的運用才能得心應手。而架構能力的提升,本質上是對你的知識脈絡(全身經絡)的反覆梳理與融會貫通的過程。具備架構思維並不難,而且極有必要。不管今天的你是不是團隊裏的一位架構師,對任何一位程序員來說,具備架構思維將會成爲讓你脫穎而出的關鍵。

這就像你沒有從事雲計算行業,但是你仍然需要理解雲計算的本質,需要駕馭雲計算。你也不必去做出一個瀏覽器,但是你需要理解它們的思考方式,因爲你在深度依賴於它們。

作者介紹:

許式偉,七牛雲 CEO,ECUG 社區發起人。曾就職於金山、盛大,在搜索和分佈式存儲相關技術領域有十幾年的研發經驗。在金山,他以首席架構師的身份主導了 WPS Office 2005 的架構設計和開發。在創立金山實驗室後,作爲技術總監主導了分佈式存儲開發,後加入盛大創新院,併成功推出“盛大網盤”和“盛大雲”。

這些年,他扛過國產軟件研發的大旗,忍受過在 Office 和盜版夾擊下的艱難求生,經歷過公司轉型和個人轉型交織的洗禮。2011 年,他成爲一名創業者,建立了七牛,專注企業級存儲服務。

這個專欄是他第一次完整、系統地分享自己的架構經驗和思考,老許將毫無保留地分享自己近 20 年的經驗總結,讓你一定能夠學有所得

推薦閱讀:

許式偉:畢業 2 年成爲首席架構師,我的技術學習方法論

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章