北哥在前文陸續(xù)總結了程序員成長所具備的核心能力,以及Java程序員成長過程中應學習的基礎知識。
在一個Java程序員工作3、5年之后,已經可以承擔起大部分的核心開發(fā)工作,成長為團隊中的高級開發(fā)人員。大部分工作中遇到的問題都已經可以自行解決。這個階段很多同學會面臨著新的成長困惑,到底接下來自己還需要在哪些方面繼續(xù)提升?如何能夠成長為團隊里面的架構師呢?
市面上有很多分析和拆解架構師能力的書籍,例如《聊聊架構》《億級流量網站架構核心技術》《大型網站技術架構:核心原理與案例分析》等,書中有一些相關的實戰(zhàn)和理論知識分享。這些書籍如果有時間推薦大家去讀一讀。
今天北哥結合自己工作中的經驗,也來淺談一下如何做應用系統(tǒng)架構設計。
需要說明的是,架構師本身要求的是綜合能力,架構也分為業(yè)務架構、應用系統(tǒng)架構、技術架構、數據架構等多個維度多個細分領域,但今天分享的關于架構的相關內容,更多還是側重在服務端的應用系統(tǒng)架構。
01?指導思想
作為一個架構師,在做應用系統(tǒng)架構時,最好逐步沉淀自己的一套指導思想,指導思想用于在做架構設計過程中遇到困惑或遇事不決時的一個指引。我個人總結下來的經驗有以下三點
平衡和取舍
架構是一個復雜的工作,既要考慮當下的需求,還要關注未來可能的變化;既要考慮的足夠全面,還要簡單容易實現;既要衡量實現成本,還要關注落地的效率。這些無不意味著在做架構時需做好平衡,學會取舍。
迭代和演進
一個好的架構,一定是經過長期迭代演進而來的。在做架構設計時,受限于當前已經明確的需求,往往無法對未來考慮的那么全面。即使在做架構設計時已經考慮到了方方面面,系統(tǒng)上線后也會遇到一些新的未知問題,并且隨著需求的不斷迭代,又會引入新的變化和挑戰(zhàn),因此持續(xù)的對架構做優(yōu)化和迭代演進,是必須要重視的。
聚焦業(yè)務需求
沒有毫無瑕疵完美的架構,也沒有一成不變適合所有業(yè)務的架構,只有適合當前業(yè)務和產品需求的架構。我們可以借鑒、吸收別人的經驗和實踐總結,但最合適的架構一定是結合業(yè)務的實際需求設計和演變出來的。脫離業(yè)務需求設計的架構一定會在開發(fā)中遇到新的問題。
02?架構設計目標
在做應用系統(tǒng)架構設計時,應遵循一些普適的架構設計目標。這些目標包括
可實現的:架構被設計出來,一定是需要能夠被實現和落地的,如果設計架構所采用的技術還沒成熟或不具備生產環(huán)境可用性,這種架構只能停留在理論階段,不具備落地的可行性,這樣的架構也就沒有特別大的價值和意義。
可擴展的:雖然無法預知需求未來的變化,但有些場景下,我們設計的架構也應該具備當用戶量、帶寬、數據量等增長時,具備較好的擴展性;除此之外,在做需求分析時,把系統(tǒng)、領域服務甚至模塊做好規(guī)劃和設計,能夠合理的應對未來需求膨脹可能帶來的問題,也是架構可擴展性的一種體現。
高可用的:系統(tǒng)架構需要考慮各種異常情況下系統(tǒng)可用性,如流量的突然爆發(fā)的消峰限流,某個服務或接口故障后的降級等,通過在架構中設計的各種措施保障整個應用系統(tǒng)是高可用的。
可衡量的:應用系統(tǒng)架構設計最終都需要落地到代碼層面實現,提供出可線上發(fā)布的系統(tǒng)和服務。我們在做系統(tǒng)架構設計時,需要根據業(yè)務數據的預估,設計出滿足一定量級的系統(tǒng)數據指標,將架構設計的結果量化。在遇到系統(tǒng)負載過高需要擴容時,就可以參考定量的數據指標預估出所需的服務器和資源等。
接下來從業(yè)務需求分析開始,到最終系統(tǒng)上線運營,按照不同階段需要關注的知識和內容,來說明整個應用系統(tǒng)架構設計過程需要考慮的問題。
03?需求分析階段
正如前文所述,系統(tǒng)架構應該是聚焦業(yè)務需求的,業(yè)務需求分析,是做系統(tǒng)架構設計的必要前置。這里簡述下我在需求分析階段工作的大致思路。
正常情況下,進入到架構師層面的需求,都經過了業(yè)務人員和產品人員至少一輪的討論溝通,或已經有基本的業(yè)務和產品需求雛形,或已經產出業(yè)務的MRD(業(yè)務需求說明書)或產品的PRD(產品需求說明書)。這時架構師進入后需要再和業(yè)務及產品同學進行充分的討論溝通,明確和產出以下幾點信息:
確定清楚業(yè)務目標,搞清楚業(yè)務需要解決的核心問題是什么,通過產品和系統(tǒng)期望帶來的效果是怎樣的。
進行業(yè)務流程梳理和業(yè)務建模。業(yè)務建模的核心在于梳理清楚用戶角色、業(yè)務場景、流程和相關規(guī)則策略。弄清楚不同用戶角色在哪些場景下可以進行什么樣的操作,由此對業(yè)務有更清晰的全局認識。
根據業(yè)務模型、業(yè)務產出的MRD或產品產出的PRD,整理出大概的子系統(tǒng)和功能列表。功能列表先從第一層級梳理,再層層細化,一般以不超過四層為宜。如第一層級分為用戶管理、訂單管理、售后退換貨管理等。第二層級中用戶管理再細分為注冊登陸,基礎資料維護、禁用啟用等,依次類推。
根據業(yè)務模型和功能列表,預估和完善非功能性需求,如對總用戶量、同時在線用戶量、系統(tǒng)訪問量等非功能需求,系統(tǒng)性能、響應時間、qps等系統(tǒng)性能要求,系統(tǒng)工期、人員投入、項目組織結構、其它成本等項目約束條件等。
在需求分析階段,我會最終產出一份基于業(yè)務模型拆解出的功能需求列表和非功能需求列表。這將作為后續(xù)應用系統(tǒng)架構的核心參考和依據。

04?架構設計階段
在需求分析階段完成后,就進入到系統(tǒng)架構設計階段。
在系統(tǒng)架構設計階段,我一般會首先做數據建模。根據業(yè)務模型和功能列表,已經可以分清楚大概的系統(tǒng)、模塊和功能,由此數據庫的概念模型基本能夠確定下來。通過數據庫的概念模型設計,結合需求分析階段產出的功能需求列表,整個系統(tǒng)的詳細需求基本可以被印在大腦中了。同時經過概念模型的設計,不同數據實體之間的關系已經相對清晰,服務或領域的劃分也具備初步的雛形了。
完成數據庫的概念模型后,開始進行詳細的系統(tǒng)架構設計和技術選型階段。
在系統(tǒng)架構設計階段,我會按照分層架構設計的思想,逐步做細化展開。
在目前的主流技術方案中,前后端分離基本上是默認的標準,核心原因一方面是前后端技術演進快速發(fā)展,技術專業(yè)人員分工更明確;另一方面當前的產品開始移動化,前后端一體的架構無法支撐當前移動端特別是App類應用的開發(fā),前后端分離也成為不得不為之的舉措。
按照分層架構設計的思想,將整個架構分為前端接入層、服務層、數據訪問層、數據存儲層。在部分高并發(fā)的系統(tǒng)中,還會有緩存相關技術貫穿在整個架構層級之間。
前端接入層
首先,在前端接入層,主要解決用戶流量從終端發(fā)起請求到被應用服務器接收之前這一段的問題。
在前端接入層,核心需要解決終端展現時的響應速度和穩(wěn)定性。
在傳統(tǒng)的PC互聯網場景下,大部分產品和應用以瀏覽器為終端,通過網頁的方式展現在用戶面前,如京東、淘寶等電商類的網頁版。在終端層面,因為用戶請求量巨大,會借助頁面靜態(tài)化、CDN等方式,提升頁面加載速度。在請求層面,為了提升穩(wěn)定性和應對更大的流量挑戰(zhàn),在流量進入到應用服務器前,會通過使用DNS、軟硬件負載的方式進行流量分流,將請求打到不同的應用服務器上。這里會使用到的硬件負載有F5等,而軟件負載主要通過nginx實現,早期還有LVS、Haproxy的方案等。
服務層
說完接入層,再來看服務層。服務是應用系統(tǒng)的核心,承擔著業(yè)務和產品核心需求和邏輯的實現。
在服務層,需要解決的重點問題問題是,服務是否可以靈活快速的水平擴展,以應對未來系統(tǒng)可能的訪問量劇增。
為解決這個問題,需要對是否進行分布式架構設計進行權衡。分布式架構設計的核心是通過對服務的解耦,來解決應用的水平擴展問題,降低單服務單機器的壓力。如果系統(tǒng)所需要承擔的流量在可預期的未來會有較大的增長,分布式架構設計就是有必要的。而如果系統(tǒng)流量在很長一段時間內都相對有限且平穩(wěn),則分布式架構就顯得沒那么必要。這里即需要做好平衡和取舍。分布式架構雖然能夠帶來服務水平擴展的便捷性,以應對未來可能的系統(tǒng)流量大幅增長,但需要付出較大的系統(tǒng)維護成本。
如果選擇暫時不采用分布式架構,服務層也同樣可以在工程層面,按照服務的接口層、服務的邏輯層和服務的數據層進行劃分模塊和子模塊,然后在代碼構建打包時集成到一個單體應用作為一個jar或war包一起發(fā)布。根據我之前的經驗,在一個業(yè)務和產品的早期階段,采用模塊化劃分的單體應用方式的架構,可以快速完成產品MVP版本的上線試錯,當業(yè)務發(fā)展到一定規(guī)模后再啟動分布式架構的服務化改造,也不失為一個較好的選擇。
無論在一開始就選定分布式架構方案,還是在后期做分布式架構的服務化改造時,都會面臨著另外一個選型問題:到底是采用分布式服務還是微服務方式來構建應用。
分布式服務和微服務是在分布式架構演進過程中產生的不同概念,按照我的理解,分布式服務關注的重點是分布式,重點解決服務的壓力負載分擔,而微服務重點關注的是服務的單元顆粒度大小,更關注服務的原子性、獨立性。二者都是為了解耦合,但在解耦合的顆粒度上稍有不同。具體的選擇也需要根據應用系統(tǒng)的規(guī)模、領域劃分等綜合考量。
落地到分布式服務的架構技術選型上,有以傳統(tǒng)的RPC框架為主導的技術體系,和以Spring Boot微服務框架為基礎的Spring Cloud全家桶。傳統(tǒng)的RPC框架以早期阿里開源的Dubbo框架為代表,核心的實現是基于動態(tài)代理+反射的方式來實現服務之間的接口通信,服務和服務之間的底層調用是基于socket來實現數據傳輸交互的。而Spring Cloud全家桶,核心是基于Http協議實現的一套微服務框架,服務和服務之間的調用是通過Http接口實現交互的的。
相比Spring Cloud,RPC框架一般具有可自定義數據結構、網絡傳輸速度快、效率高等特點,而Spring?Cloud因為是基于Http協議進行網絡傳輸,消息的包體大小受Http協議限制做了封裝顯得相對臃腫,在網絡傳輸時效率相對低一些,但Spring Cloud因有一整套組件和生態(tài)的支撐,因此在不做過多性能苛求的情況下,也是目前可以快速采用的方案之一。另外一種將二者結合的方案,利用Spring Cloud設計和實現接口的接入網關,再通過網關將請求轉發(fā)到RPC服務中,則是目前一些大型應用普遍采用的方案。
在使用Spring Cloud或RPC框架的過程中,另外一個需要關注的問題是服務之間的耦合問題。雖然分布式服務或微服務本身就是為了解決耦合問題,但應用和應用、服務與服務之間的依賴關系并不因為使用Spring Cloud或RPC框架就消失了,在一些場景下,適度的服務之間的依賴是允許且必要的,但過度的服務之間依賴,甚至發(fā)展成服務與服務之間相互依賴,就是需要避免的一種情況了。
通過消息中間件,將原本有上下游關系的依賴,通過消息解耦,從而讓服務和服務之間避免強依賴,是其中的一個解決方案。
常用的消息中間件有RabbitMQ、RocketMQ、Kafka等。
數據訪問層
說完服務層,再來看數據訪問層。所有的應用都離不開數據,數據是一個系統(tǒng)的靈魂所在。數據訪問層主要用于完成服務層和數據存儲層之間數據的交互。
因為數據存儲方式的多樣性,數據訪問層一個重要功能是實現對不同數據存儲方式的封裝,盡量做到對服務層屏蔽具體的數據存儲細節(jié)。
另一個數據訪問層的重要作用,是解決數據存儲場景下的資源管理問題,包括連接池資源、分庫分表、讀寫分離等。具體是否需要做分庫分表、讀寫分離等,需要根據應用的實際數據量大小、選擇的數據存儲方式等做綜合考量。
數據存儲層
最后,再來考慮數據存儲層的搭建和選型。
數據存儲層是用于將具體應用產生的數據持久化。不同的數據存儲方式適用的業(yè)務場景也有很大不同。如對事務要比較高,一般采用關系型數據庫如Mysql、Oracle等;對數據結構和表結構擴展性要求較靈活的可以采用NoSQL數據庫如MongoDB、CouchDB等;如果需要存儲的數據量非常龐大,可以選擇目前基于hdfs的存儲方案如Hbase、Hive等;還會有對文件、圖片等有存儲需求的,可以采用分布式文件存儲或云存儲的方式等。數據存儲的方案本身沒有好壞之分,具體還是要分析業(yè)務的實際需求來做平衡和選擇。
關于緩存
除了以上所述的幾個層級,在大部分互聯網應用中,當系統(tǒng)訪問用戶量達到一定量級,或QPS較高的場景下,還會通過增加緩存來降低系統(tǒng)和接口的響應時間,提升系統(tǒng)的性能。常用的緩存框架有Redis、Memcache等。
在架構設計階段,我們把整個系統(tǒng)按照分層的思想做拆解說明,根據業(yè)務的實際需求,對各層中采用的技術和方案做平衡和取舍。架構設計階段完成并不意味著整個應用系統(tǒng)架構的完成。接下來需要將架構設計落地到代碼中。
05?編碼階段
在架構設計方案完成后,對于開發(fā)工程師來說,已經可以根據架構設計方案來指導進行詳細需求設計和編碼。
對于架構師來說,在這個階段需要重點關注的有以下幾點:
工程結構:良好的工程結構,可以大幅降低后續(xù)代碼的維護成本和大團隊的協作成本。每一層的工程結構也會有所側重和不同,我們可以在平時沉淀適合自己企業(yè)的工程結構腳手架,在需要時一鍵創(chuàng)建,既能提升效率,還可以統(tǒng)一工程模板。
設計模式:針對復雜的需求,架構師需要重點關注,將不同設計模式組合、擴展應用到代碼設計中,提升代碼的可擴展性和可維護性。
代碼模板:代碼模板可以統(tǒng)一代碼風格,提升代碼的可讀性和可維護性。
代碼檢查:通過對代碼的檢查,發(fā)現不合理的代碼組織和設計、潛在的代碼隱患等等。也可以借助一些第三方插件或工具如PMD、Findbugs等輔助做檢查。
06?上線運營階段
一個好的架構,一定是需要經歷線上系統(tǒng)的檢驗的。在測試人員完成質量測試后,需要對應用系統(tǒng)做上線發(fā)布,進入到上線運營階段。
在上線運營階段,架構師核心職責是做好各項監(jiān)控和告警指標的設定。
在監(jiān)控層面,首選需要對應用系統(tǒng)相關的各項性能指標做監(jiān)控。通過一些開源或企業(yè)自研的監(jiān)控工具,需要對應用系統(tǒng)所采用的物理資源如磁盤、內存、CPU、網絡等進行監(jiān)控;需要對數據存儲組件如數據庫的慢查詢、I/O、庫大小等進行監(jiān)控;對中間件如RabbitMQ、Redis等讀寫、容量等進行監(jiān)控;對應用系統(tǒng)性能如接口響應時長、95線、99線的監(jiān)控等等。
另外一個重要的監(jiān)控對象是業(yè)務指標的監(jiān)控,如一段時間內的登陸用戶量、短信發(fā)送量、訂單下單量、訂單支付量等等。業(yè)務指標的監(jiān)控往往能反映出一些系統(tǒng)層面的異常,引導去追究引起業(yè)務指標異常的根本原因,從而提升系統(tǒng)的可靠性和穩(wěn)定性。
具體建立哪些監(jiān)控指標需要根據不同的監(jiān)控對象進行合理的設定。
建立完監(jiān)控指標后,還需要建立告警體系,將異常的指標及時告警通知出來。一般的監(jiān)控系統(tǒng)都會有提供類似短信、釘釘等告警方式的接入。
最后,在上線運營階段還需要收集和關注系統(tǒng)的日志,及時排查修復異常,保障系統(tǒng)的穩(wěn)健運行。
以上是從一個業(yè)務的需求階段開始,到整個業(yè)務的應用系統(tǒng)上線運營,作為一個架構師需要關注的方方面面。
當然,其中的每一個架構點和技術方案,展開來看都是一個很大的課題。當你具備架構的全局思維之后,接下來就可以深入到不同領域專研,并在工作中不斷實踐和試錯,最終完成自身技能的進階。
自計算機誕生以來,各項軟硬件技術即在不斷迭代更新,催生著軟件架構的不斷升級換代。而隨著大數據云計算5G時代的帶領,新的業(yè)務場景如音視頻、直播、物聯網等等業(yè)務挑戰(zhàn)也會隨之而來,我們對架構的追求也永無止境。
希望你我都可以在持續(xù)的架構演進中,不斷學習,持續(xù)進步。
相關閱讀