北哥在前文陸續總結了程序員成長所具有的核心能力,以及Java程序員成長過程當中應學習的基礎知識。在一個Java程序員工做三、5年以後,已經能夠承擔起大部分的核心開發工做,成長爲團隊中的高級開發人員。大部分工做中遇到的問題都已經能夠自行解決。這個階段不少同窗會面臨着新的成長困惑,到底接下來本身還須要在哪些方面繼續提高?如何可以成長爲團隊裏面的架構師呢?前端
市面上有不少分析和拆解架構師能力的書籍,例如《聊聊架構》《億級流量網站架構核心技術》《大型網站技術架構:核心原理與案例分析》等,書中有一些相關的實戰和理論知識分享。這些書籍若是有時間推薦你們去讀一讀。nginx
今天北哥結合本身工做中的經驗,也來淺談一下如何作應用系統架構設計。程序員
須要說明的是,架構師自己要求的是綜合能力,架構也分爲業務架構、應用系統架構、技術架構、數據架構等多個維度多個細分領域,但今天分享的關於架構的相關內容,更多仍是側重在服務端的應用系統架構。sql
做爲一個架構師,在作應用系統架構時,最好逐步沉澱本身的一套指導思想,指導思想用於在作架構設計過程當中遇到困惑或遇事不決時的一個指引。我我的總結下來的經驗有如下三點數據庫
架構是一個複雜的工做,既要考慮當下的需求,還要關注將來可能的變化;既要考慮的足夠全面,還要簡單容易實現;既要衡量實現成本,還要關注落地的效率。這些無不意味着在作架構時需作好平衡,學會取捨。後端
一個好的架構,必定是通過長期迭代演進而來的。在作架構設計時,受限於當前已經明確的需求,每每沒法對將來考慮的那麼全面。即便在作架構設計時已經考慮到了方方面面,系統上線後也會遇到一些新的未知問題,而且隨着需求的不斷迭代,又會引入新的變化和挑戰,所以持續的對架構作優化和迭代演進,是必需要重視的。設計模式
沒有毫無瑕疵完美的架構,也沒有一成不變適合全部業務的架構,只有適合當前業務和產品需求的架構。咱們能夠借鑑、吸取別人的經驗和實踐總結,但最合適的架構必定是結合業務的實際需求設計和演變出來的。脫離業務需求設計的架構必定會在開發中遇到新的問題。瀏覽器
在作應用系統架構設計時,應遵循一些普適的架構設計目標。這些目標包括緩存
接下來從業務需求分析開始,到最終系統上線運營,按照不一樣階段須要關注的知識和內容,來講明整個應用系統架構設計過程須要考慮的問題。服務器
正如前文所述,系統架構應該是聚焦業務需求的,業務需求分析,是作系統架構設計的必要前置。這裏簡述下我在需求分析階段工做的大體思路。正常狀況下,進入到架構師層面的需求,都通過了業務人員和產品人員至少一輪的討論溝通,或已經有基本的業務和產品需求雛形,或已經產出業務的MRD(業務需求說明書)或產品的PRD(產品需求說明書)。這時架構師進入後須要再和業務及產品同窗進行充分的討論溝通,明確和產出如下幾點信息:
在需求分析階段完成後,就進入到系統架構設計階段。
在系統架構設計階段,我通常會首先作數據建模。根據業務模型和功能列表,已經能夠分清楚大概的系統、模塊和功能,由此數據庫的概念模型基本可以肯定下來。經過數據庫的概念模型設計,結合需求分析階段產出的功能需求列表,整個系統的詳細需求基本能夠被印在大腦中了。同時通過概念模型的設計,不一樣數據實體之間的關係已經相對清晰,服務或領域的劃分也具有初步的雛形了。完成數據庫的概念模型後,開始進行詳細的系統架構設計和技術選型階段。
在系統架構設計階段,我會按照分層架構設計的思想,逐步作細化展開。在目前的主流技術方案中,先後端分離基本上是默認的標準,核心緣由一方面是先後端技術演進快速發展,技術專業人員分工更明確;另外一方面當前的產品開始移動化,先後端一體的架構沒法支撐當前移動端特別是App類應用的開發,先後端分離也成爲不得不爲之的舉措。
按照分層架構設計的思想,將整個架構分爲前端接入層、服務層、數據訪問層、數據存儲層。在部分高併發的系統中,還會有緩存相關技術貫穿在整個架構層級之間。
前端接入層
首先,在前端接入層,主要解決用戶流量從終端發起請求到被應用服務器接收以前這一段的問題。
在前端接入層,核心須要解決終端展示時的響應速度和穩定性。
在傳統的PC互聯網場景下,大部分產品和應用以瀏覽器爲終端,經過網頁的方式展示在用戶面前,如京東、淘寶等電商類的網頁版。在終端層面,由於用戶請求量巨大,會藉助頁面靜態化、CDN等方式,提高頁面加載速度。在請求層面,爲了提高穩定性和應對更大的流量挑戰,在流量進入到應用服務器前,會經過使用DNS、軟硬件負載的方式進行流量分流,將請求打到不一樣的應用服務器上。這裏會使用到的硬件負載有F5等,而軟件負載主要經過nginx實現,早期還有LVS、Haproxy的方案等。
服務層
說完接入層,再來看服務層。服務是應用系統的核心,承擔着業務和產品核心需求和邏輯的實現。
在服務層,須要解決的重點問題問題是,服務是否能夠靈活快速的水平擴展,以應對將來系統可能的訪問量劇增。
爲解決這個問題,須要對是否進行分佈式架構設計進行權衡。分佈式架構設計的核心是經過對服務的解耦,來解決應用的水平擴展問題,下降單服務單機器的壓力。若是系統所須要承擔的流量在可預期的將來會有較大的增加,分佈式架構設計就是有必要的。而若是系統流量在很長一段時間內都相對有限且平穩,則分佈式架構就顯得沒那麼必要。這裏即須要作好平衡和取捨。
分佈式架構雖然可以帶來服務水平擴展的便捷性,以應對將來可能的系統流量大幅增加,但須要付出較大的系統維護成本。若是選擇暫時不採用分佈式架構,服務層也一樣能夠在工程層面,按照服務的接口層、服務的邏輯層和服務的數據層進行劃分模塊和子模塊,而後在代碼構建打包時集成到一個單體應用做爲一個jar或war包一塊兒發佈。根據我以前的經驗,在一個業務和產品的早期階段,採用模塊化劃分的單體應用方式的架構,能夠快速完成產品MVP版本的上線試錯,當業務發展到必定規模後再啓動分佈式架構的服務化改造,也不失爲一個較好的選擇。
不管在一開始就選定分佈式架構方案,仍是在後期作分佈式架構的服務化改造時,都會面臨着另一個選型問題:究竟是採用分佈式服務仍是微服務方式來構建應用。
分佈式服務和微服務是在分佈式架構演進過程當中產生的不一樣概念,按照個人理解,分佈式服務關注的重點是分佈式,重點解決服務的壓力負載分擔,而微服務重點關注的是服務的單元顆粒度大小,更關注服務的原子性、獨立性。兩者都是爲了解耦合,但在解耦合的顆粒度上稍有不一樣。具體的選擇也須要根據應用系統的規模、領域劃分等綜合考量。
落地到分佈式服務的架構技術選型上,有以傳統的RPC框架爲主導的技術體系,和以Spring Boot微服務框架爲基礎的Spring Cloud全家桶。
傳統的RPC框架以早期阿里開源的Dubbo框架爲表明,核心的實現是基於動態代理+反射的方式來實現服務之間的接口通訊,服務和服務之間的底層調用是基於socket來實現數據傳輸交互的。而Spring Cloud全家桶,核心是基於Http協議實現的一套微服務框架,服務和服務之間的調用是經過Http接口實現交互的的。相比Spring Cloud,RPC框架通常具備可自定義數據結構、網絡傳輸速度快、效率高等特色,而Spring Cloud由於是基於Http協議進行網絡傳輸,消息的包體大小受Http協議限制作了封裝顯得相對臃腫,在網絡傳輸時效率相對低一些,但Spring Cloud因有一整套組件和生態的支撐,所以在不作過多性能苛求的狀況下,也是目前能夠快速採用的方案之一。另一種將兩者結合的方案,利用Spring Cloud設計和實現接口的接入網關,再經過網關將請求轉發到RPC服務中,則是目前一些大型應用廣泛採用的方案。
在使用Spring Cloud或RPC框架的過程當中,另一個須要關注的問題是服務之間的耦合問題。雖然分佈式服務或微服務自己就是爲了解決耦合問題,但應用和應用、服務與服務之間的依賴關係並不由於使用Spring Cloud或RPC框架就消失了,在一些場景下,適度的服務之間的依賴是容許且必要的,但過分的服務之間依賴,甚至發展成服務與服務之間相互依賴,就是須要避免的一種狀況了。經過消息中間件,將本來有上下游關係的依賴,經過消息解耦,從而讓服務和服務之間避免強依賴,是其中的一個解決方案。經常使用的消息中間件有RabbitMQ、RocketMQ、Kafka等。
數據訪問層
說完服務層,再來看數據訪問層。全部的應用都離不開數據,數據是一個系統的靈魂所在。數據訪問層主要用於完成服務層和數據存儲層之間數據的交互。由於數據存儲方式的多樣性,數據訪問層一個重要功能是實現對不一樣數據存儲方式的封裝,儘可能作到對服務層屏蔽具體的數據存儲細節。另外一個數據訪問層的重要做用,是解決數據存儲場景下的資源管理問題,包括鏈接池資源、分庫分表、讀寫分離等。具體是否須要作分庫分表、讀寫分離等,須要根據應用的實際數據量大小、選擇的數據存儲方式等作綜合考量。
數據存儲層
最後,再來考慮數據存儲層的搭建和選型。
數據存儲層是用於將具體應用產生的數據持久化。不一樣的數據存儲方式適用的業務場景也有很大不一樣。如對事務要比較高,通常採用關係型數據庫如Mysql、Oracle等;對數據結構和表結構擴展性要求較靈活的能夠採用NoSQL數據庫如MongoDB、CouchDB等;若是須要存儲的數據量很是龐大,能夠選擇目前基於hdfs的存儲方案如Hbase、Hive等;還會有對文件、圖片等有存儲需求的,能夠採用分佈式文件存儲或雲存儲的方式等。數據存儲的方案自己沒有好壞之分,具體仍是要分析業務的實際需求來作平衡和選擇。
關於緩存
除了以上所述的幾個層級,在大部分互聯網應用中,當系統訪問用戶量達到必定量級,或QPS較高的場景下,還會經過增長緩存來下降系統和接口的響應時間,提高系統的性能。經常使用的緩存框架有Redis、Memcache等。在架構設計階段,咱們把整個系統按照分層的思想作拆解說明,根據業務的實際需求,對各層中採用的技術和方案作平衡和取捨。架構設計階段完成並不意味着整個應用系統架構的完成。接下來須要將架構設計落地到代碼中。
在架構設計方案完成後,對於開發工程師來講,已經能夠根據架構設計方案來指導進行詳細需求設計和編碼。對於架構師來講,在這個階段須要重點關注的有如下幾點:
工程結構:良好的工程結構,能夠大幅下降後續代碼的維護成本和大團隊的協做成本。每一層的工程結構也會有所側重和不一樣,咱們能夠在平時沉澱適合本身企業的工程結構腳手架,在須要時一鍵建立,既能提高效率,還能夠統一工程模板。
設計模式:針對複雜的需求,架構師須要重點關注,將不一樣設計模式組合、擴展應用到代碼設計中,提高代碼的可擴展性和可維護性。
代碼模板:代碼模板能夠統一代碼風格,提高代碼的可讀性和可維護性。
代碼檢查:經過對代碼的檢查,發現不合理的代碼組織和設計、潛在的代碼隱患等等。也能夠藉助一些第三方插件或工具如PMD、Findbugs等輔助作檢查。
一個好的架構,必定是須要經歷線上系統的檢驗的。在測試人員完成質量測試後,須要對應用系統作上線發佈,進入到上線運營階段。
在上線運營階段,架構師核心職責是作好各項監控和告警指標的設定。
在監控層面,首選須要對應用系統相關的各項性能指標作監控。經過一些開源或企業自研的監控工具,須要對應用系統所採用的物理資源如磁盤、內存、CPU、網絡等進行監控;須要對數據存儲組件如數據庫的慢查詢、I/O、庫大小等進行監控;對中間件如RabbitMQ、Redis等讀寫、容量等進行監控;對應用系統性能如接口響應時長、95線、99線的監控等等。
另一個重要的監控對象是業務指標的監控,如一段時間內的登錄用戶量、短信發送量、訂單下單量、訂單支付量等等。業務指標的監控每每能反映出一些系統層面的異常,引導去追究引發業務指標異常的根本緣由,從而提高系統的可靠性和穩定性。
具體創建哪些監控指標須要根據不一樣的監控對象進行合理的設定。
創建完監控指標後,還須要創建告警體系,將異常的指標及時告警通知出來。通常的監控系統都會有提供相似短信、釘釘等告警方式的接入。
最後,在上線運營階段還須要收集和關注系統的日誌,及時排查修復異常,保障系統的穩健運行。
以上是從一個業務的需求階段開始,到整個業務的應用系統上線運營,做爲一個架構師須要關注的方方面面。
固然,其中的每個架構點和技術方案,展開來看都是一個很大的課題。當你具有架構的全局思惟以後,接下來就能夠深刻到不一樣領域專研,並在工做中不斷實踐和試錯,最終完成自身技能的進階。
自計算機誕生以來,各項軟硬件技術即在不斷迭代更新,催生着軟件架構的不斷升級換代。而隨着大數據雲計算5G時代的帶領,新的業務場景如音視頻、直播、物聯網等等業務挑戰也會隨之而來,咱們對架構的追求也永無止境。
但願你我均可以在持續的架構演進中,不斷學習,持續進步。
相關閱讀
·END·