本部分節選自《 軟件架構設計》
軟件開發就是把一個複雜的問題分解爲一系列簡單的問題,再把一系列簡單的解決方案組合成一個複雜的解決方案。而軟件開發中最大的挑戰,就是即可以快速高效地針對需求、環境的變化作出改變,也可以持續提供穩定、高可用的服務。而軟件架構,就是軟件系統的骨骼與框架。javascript
所謂架構,見仁見智,很難有一個明確或標準的定義;但架構並不是鏡花水月或陽春白雪,有系統的地方就須要架構,大到航空飛機,小到一個電商系統裏面的一個功能組件,都須要設計和架構。抽象而言,架構就是對系統中的實體以及實體之間的關係所進行的抽象描述,是對物/信息的功能與形式元素之間的對應狀況所作的分配,是對元素之間的關係以及元素同周邊環境之間的關係所作的定義。架構能將目標系統按某個原則進行切分,切分的原則,是要便於不一樣的角色進行並行工做,結構良好的創造活動要優於毫無結構的創造活動。前端
軟件架構的核心價值,便是控制系統的複雜性,將核心業務邏輯和技術細節的分離與解耦。軟件架構是系統的草圖,它描述的對象是直接構成系統的抽象組件;各個組件之間的鏈接則明確和相對細緻地描述組件之間的通訊。在實現階段,這些抽象組件被細化爲實際的組件,好比具體某個類或者對象。在面向對象領域中,組件之間的鏈接一般用接口來實現。架構師的職責是努力訓練本身的思惟,用它去理解複雜的系統,經過合理的分解和抽象,理解並解析需求,建立有用的模型,確認、細化並擴展模型,管理架構;可以進行系統分解造成總體架構,可以正確的技術選型,可以制定技術規格說明並有效推進實施落地。java
在筆者的知識體系中,實際上將架構分爲業務架構、應用架構、雲基礎架構這幾大類,業務架構主要着眼於控制業務的複雜性,基礎架構着眼於解決分佈式系統中存在的一系列問題。不管何種架構,都但願能實現系統的可變的同時保障業務的高可用。另外一個層面,根據企業中職責的劃分,咱們每每能夠將軟件架構,及關聯的架構師劃分爲如下幾類:python
軟件架構設計的一個核心問題是可否使用重複的架構模式,即可否達到架構級的軟件重用。也就是說,可否在不一樣的軟件系統中,使用同一架構。當咱們討論軟件架構時,經常會說起軟件架構模式(Architectural Pattern)與軟件架構風格(Architectural Style)。git
軟件架構模式每每會用於具體地解決某個具體的重複的架構問題,而架構風格則是對於某個具體的架構設計方案的命名。軟件架構風格是描述某一特定應用領域中系統組織方式的慣用模式;架構風格反映了領域中衆多系統所共有的結構和語義特性,並指導如何將各個模塊和子系統有效組織成一個完整的系統。程序員
在筆者的系列文章中,CRUD、分層架構、六邊形架構、洋蔥架構、REST 以及 DDD,都算是架構風格;而 CQRS、EDA、UDLA、微服務等則被劃分到架構模式中。github
在軟件開發中,程序員每每可以脫離現實規律的束縛,創造出天馬行空的世界,其也是最具備創造力的活動之一。編程惟一須要的是創造力思惟和思惟組織能力,這意味着在軟件開發過程當中最大限制是理解咱們正在建立的對象。隨着軟件的演進,加入更多的功能點,系統變得愈來愈複雜:各個模塊(Module)間存在着各類微妙的依賴關係。系統的複雜性隨着時間積累,對於程序員來講,修改系統時考慮周全全部的的相關因素變得愈來愈困難。這就會使軟件開放進度變緩慢,而且引入 Bug,而致使會進一步延緩開發進度,增長開發成本。在任何一個系統的生命週期中,複雜性不可避免會增長;系統越大,須要更多的人開發,管理系統複雜性的工做就越困難。web
Eric Evans 在 Domain‐Driven Design 一書中吐槽了所謂的意大利麪式架構,即代碼確實作了有用的事,但很難解釋它是如何去執行的;他認爲形成這種窘境的主要緣由是,將領域問題的複雜度與技術細節的複雜度混合在了一塊兒,最終致使總體複雜度的指數級增加。面試
複雜性不是憑空而來,不少時候也不是刻意爲之,這也就意味着複雜性的增長每每不會以咱們的主觀意志爲轉移。就像房間裏的大象,咱們沒法逃避,也不能視而不見。複雜性的來源多是:算法
複雜性的應對永遠不會是一勞永逸,咱們須要不斷地推陳出新,是動態、漸進的重塑本身對軟件系統的認識,不斷認識問題和尋找更優解的持續迭代。第一個控制複雜性的途徑是代碼簡單,意圖清晰(Obvious)。例如: 減小特殊場景的處理,或變量命名一致性都能下降系統複雜性。另外一種方式就是對複雜問題的抽象而後分而治之。
本部分節選自《 領域驅動設計》
DDD 領域驅動設計,起源於 2004 年著名建模專家 Eric Evans 發表的他最具影響力的著名書籍:《Domain-Driven Design – Tackling Complexity in the Heart of Software》,Eric Evans 在該書中只是提供了一套原始理論,並無提供一套方法論,所以多年來對於 DDD 也是見仁見智。更早些時候 MartinFowler 曾經提出貧血模型與充血模型的概念,他認爲咱們大多數系統以 POJO 做爲模型,只有普通的 getter、setter 方法,沒有真正的行爲,好像缺乏血液的人,在 Evans 看來,DDD 中模型都是以充血形式存在,也就是說在 DDD 中,咱們設計的模型不只包含描述業務屬性,還要包含可以描述動做的方法,不一樣的是,領域中一些概念不能用在模型對象,如倉儲、工廠、服務等,如強加於模型中,將破壞模型的定義。
領域驅動設計的戰略核心便是將問題域與應用架構相剝離,將業務語義顯現化,把原先晦澀難懂的業務算法邏輯,經過領域對象(Domain Object),統一語言(Ubiquitous Language)轉化爲領域概念清晰的顯性化表達出來。
本部分節選自《 微服務與雲原生》
在 Web 應用程序發展的早期,大部分工程是將全部的服務端功能模塊打包到單個巨石型(Monolith)應用中,譬如不少企業的 Java 應用程序打包爲 war 包,最終會造成以下的架構:
巨石型應用易於搭建開發環境、易於測試、易於部署;其缺陷也很是明顯,沒法進行局部改動與部署,編譯時間過長,迴歸測試周期過長,開發效率下降等。集中式架構分爲標準的三層:數據訪問層、服務層和 Web 層。
在 Web2.0 時代剛剛流行的時候,互聯網應用與企業級應用並無本質的區別,集中式架構分爲標準的三層:數據訪問層、服務層和 Web 層。
SOA(Service-Oriented Architecture) 面向服務架構,是在互聯網應用規模迅速增加,集中式架構已沒法作到無限制地提高系統的吞吐量的背景下,產生的涉及模塊化開發、分佈式擴展部署等相對寬泛的概念。
SOA 是一個組件模型,它將應用程序的不一樣功能單元(稱爲服務)經過這些服務之間定義良好的接口和契約聯繫起來。SOA 中的接口獨立於實現服務的硬件平臺、操做系統和編程語言,採用中立的方式進行定義。這使得構建在各類各樣的系統中的服務能夠以一種統一和通用的方式進行交互。面向服務架構,它能夠根據需求經過網絡對鬆散耦合的粗粒度應用組件進行分佈式部署、組合和使用。服務層是 SOA 的基礎,能夠直接被應用調用,從而有效控制系統中與軟件代理交互的人爲依賴性。
實施 SOA 的關鍵目標是實現企業 IT 資產的最大化做用。要實現這一目標,就要在實施 SOA 的過程當中牢記如下特徵:可從企業外部訪問、隨時可用、粗粒度的服務接口分級、鬆散耦合、可重用的服務、服務接口設計管理、標準化的服務接口、支持各類消息模式、精肯定義的服務契約。
服務消費者(Service Consumer)能夠經過發送消息來調用服務,這些消息由一個服務總線(Service Bus)轉換後發送給適當的服務實現。這種服務架構能夠提供一個業務規則引(Business Rules Engine),該引擎允許業務規則被合併在一個服務裏或多個服務裏。這種架構也提供了一個服務管理基礎(Service Management Infrastructure),用來管理服務,相似審覈,列表(billing),日誌等功能。此外,該架構給企業提供了靈活的業務流程,更好地處理控制請求(Regulatory Requirement),例如 Sarbanes Oxley(SOX),而且能夠在不影響其餘服務的狀況下更改某項服務。
因爲分佈式系統十分複雜,所以產生了大量的用於簡化分佈式系統開發的分佈式中間件和分佈式數據庫,服務化的架構設計理念也被愈來愈多的公司所認同。以下是 Dubbo 官方文檔公佈了一張有關 SOA 系統演化過程的圖片:
微服務(Microservices Architecture Pattern)由 Martin Fowler 在 2014 年提出的,是但願將某個單一的單體應用,轉化爲多個能夠獨立運行、獨立開發、獨立部署、獨立維護的服務或者應用的聚合,從而知足業務快速變化及分佈式多團隊並行開發的需求。如康威定律(Conway’s Law)所言,任何組織在設計一套系統(廣義概念)時,所交付的設計方案在結構上都與該組織的通訊結構保持一致,微服務與微前端不只僅是技術架構的變化,還包含了組織方式、溝通方式的變化。
對於微服務,不一樣背景的人也有不一樣的看法,對於熟悉 SOA 的開發者,微服務也能夠認爲是去除了 ESB 的 SOA 的一種實現方案;ESB 是 SOA 架構中的中心總線,設計圖形應該是星形的,而微服務是去中心化的分佈式軟件架構。SOA 更多強調重用,而微服務偏向於重寫。SOA 偏向水平服務,微服務偏向垂直服務;SOA 偏向自上而下的設計,微服務偏向自下而上的設計。
微服務與微前端原理和軟件工程,面向對象設計中的原理一樣相通,都是遵循單一職責(Single Responsibility)、關注分離(Separation of Concerns)、模塊化(Modularity)與分而治之(Divide & Conquer)等基本的原則。從巨石型應用到微服務的衍化也並不是一蹴而就,以下圖也演示了簡單的漸進式替代過程:
雲原生是經過構建團隊、文化和技術,利用自動化和架構來管理系統的複雜性和解放生產力。
— Joe Beda,Heotio CTO,聯合創始人
Pivotal 是雲原生應用的提出者,並推出了 Pivotal Cloud Foundry 雲原生應用平臺和 Spring 開源 Java 開發框架,成爲雲原生應用架構中先驅者和探路者。早在 2015 年 Pivotal 公司的 Matt Stine 寫了一本叫作遷移到雲原生應用架構的小冊子,其中探討了雲原生應用架構的幾個主要特徵:符合 12 Factors 應用、面向微服務架構、自服務敏捷架構、基於 API 的協做以及抗脆弱性。2015 年 Google 主導成立了雲原生計算基金會(CNCF),起初 CNCF 對雲原生(Cloud Native)的定義包含如下三個方面:應用容器化、面向微服務架構、應用支持容器的編排調度。
雲原生應用程序簡單地定義爲從頭開始爲雲計算架構而構建應用程序;這意味着,若是咱們將應用程序設計爲預期將部署在分佈式、可擴展的基礎架構上,咱們的應用程序就是雲原生的。隨着公共雲將承載愈來愈多的算力,將來雲計算將是主流的 IT 能力交付方式,CNCF 也對雲原生進行了從新定義:雲原生技術有利於各組織在公有云、私有云和混合雲等新型動態環境中,構建和運行可彈性擴展的應用;雲原生的表明技術包括容器、服務網格、微服務、不可變基礎設施和聲明式 API。
這些技術組合搭配,可以構建容錯性好、易於管理和便於觀察的鬆耦合系統;再結合可靠的自動化手段,雲原生技術可以使工程師輕鬆地對系統做出頻繁和可預測的重大變動。因而可知,雲原生是保障系統能力靈動性地有效抓手;雲原生技術有利於各組織在公有云、私有云和混合雲等新型動態環境中,構建和運行可彈性擴展的應用。微服務架構很是適合雲原生應用程序;可是,雲原生一樣存在着必定的限制,若是你的雲原生應用程序部署在 AWS 等公有云上,則雲原生 API 不是跨雲平臺的。
雲原生應用的關鍵屬性包括了:使用輕量級的容器打包、使用最合適的語言和框架開發、以鬆耦合的微服務方式設計、以 API 爲中心的交互和協做、無狀態和有狀態服務在架構上界限清晰、不依賴於底層操做系統和服務器、部署在自服務、彈性的雲基礎設施上、經過敏捷的 DevOps 流程管理、自動化能力、經過定義和策略驅動的資源分配。雲原生是分佈式應用當下重要的發展路徑,其終態應當是 Distributionless,全部與分佈式相關的問題由雲平臺解,分佈式應用的開發會跟傳統應用的開發同樣方便,甚至更加便捷。
本部分節選自《 分佈式基礎架構之虛擬化與編排》
虛擬機由某些特定的硬件和內核虛擬化組成,運行客戶操做系統。稱爲管理程序的軟件建立虛擬化硬件,其能夠包括虛擬磁盤,虛擬網絡接口,虛擬 CPU 等。虛擬機還包括能夠與此虛擬硬件通訊的賓客內核。管理程序能夠託管,這意味着它是一些在主機操做系統(MacOS)上運行的軟件,如示例中所示。它也能夠是裸機,直接在機器硬件上運行(替換你的操做系統)。不管哪一種方式,管理程序方法都被認爲是重量級的,由於它須要虛擬化多個部分(若是不是所有硬件和內核)。
VM 須要硬件虛擬化才能實現機器級隔離,而容器則只須要在同一操做系統內進行隔離操做。 隨着隔離空間數量的增長,開銷差別變得很是明顯。
在過去幾年裏,雲平臺發展迅速,但其中困擾運維工程師最多的,是須要爲各類迥異的開發語言安裝相應的運行時環境。雖然自動化運維工具能夠下降環境搭建的複雜度,但仍然不能從根本上解決環境的問題。
Docker 的出現成爲了軟件開發行業新的分水嶺,容器技術的成熟也標誌着技術新紀元的開啓。Docker 提供了讓開發工程師能夠將應用和依賴封裝到一個可移植的容器中的能力,這項舉措使得 Docker 大有席捲整個軟件行業而且進而改變行業遊戲規則的趨勢,這像極了當年智能手機剛出現時的場景——改變了整個手機行業的遊戲規則。Docker 經過集裝箱式的封裝方式,讓開發工程師和運維工程師都可以以 Docker 所提供的鏡像分發的標準化方式發佈應用,使得異構語言再也不是捆綁團隊的枷鎖。
容器是包含應用程序代碼,配置和依賴關係的軟件包,可提供運營效率和生產力。容器爲咱們提供了可預測的,可重複的和不可變的運行預期,容器的興起是 DevOps 即服務的一個巨大推進因素,能夠克服當今面臨的最大安全障礙。容器化經過在操做系統級別進行虛擬化來使應用程序可移植,從而建立基於內核的隔離的封裝系統。容器化的應用程序能夠放在任何地方,無需依賴項運行或須要整個 VM,從而消除了依賴關係。
做爲獨立的單元,容器可以在任何主機操做系統,CentOS,Ubuntu,MacOS,甚至是像 Windows 這樣的非 UNIX 系統中運行。容器還充當標準化的工做或計算單元。一個常見的範例是每一個容器運行單個 Web 服務器,數據庫的單個分片或單個 Spark 工做程序等,只須要擴展容器的數量就可以便捷地擴展應用。每一個容器都有一個固定的資源配置(CPU,RAM,線程數等),而且擴展應用程序須要只擴展容器的數量而不是單個資源原語。當應用程序須要按比例放大或縮小時,這爲工程師提供了更容易的抽象。容器也是實現微服務架構的一個很好的工具,每一個微服務只是一組協做容器。例如,可使用單個主容器和多個從容器來實現 Redis 微服務。
隨着虛擬化技術的成熟和分佈式架構的普及,用來部署、管理和運行應用的雲平臺被愈來愈多地說起。IaaS、PaaS 和 SaaS 是雲計算的三種基本服務類型,分別表示關注硬件基礎設施的基礎設施即服務、關注軟件和中間件平臺的平臺即服務,以及關注業務應用的軟件即服務。容器的出現,使原有的基於虛擬機的雲主機應用,完全轉變爲更加靈活和輕量的容器與編排調度的雲平臺應用。
然而容器單元愈來愈散落使得管理成本逐漸上升,你們對容器編排工具的需求史無前例的強烈,Kubernetes、Mesos、Swarm 等爲雲原生應用提供了強有力的編排和調度能力,它們是雲平臺上的分佈式操做系統。容器編排是一般能夠部署多個容器以經過自動化實現應用程序的過程。像 Kubernetes 和 Docker Swarm 這樣的容器管理和容器編排引擎,使用戶可以指導容器部署並自動執行更新,運行情況監視和故障轉移過程。
Kubernetes 是目前世界範圍內關注度最高的開源項目,它是一個出色的容器編排系統,用於提供一站式服務。Kubernetes 出身於互聯網行業巨頭 Google,它借鑑了由上百位工程師花費十多年時間打造的 Borg 系統的理念,安裝極其簡易,網絡層對接方式十分靈活。Kubernetes 和 Mesos 的出色表現給行業中各種工程師的工做模式帶來了顛覆性的改變。他們不再用關注每一臺服務器,當服務器出現問題時,只要將其換掉便可。業務開發工程師沒必要再過度關注非功能需求,只需專一本身的業務領域便可。而中間件開發工程師則須要開發出健壯的雲原生中間件,用來鏈接業務應用與雲平臺。
Kubernetes、Service Mesh 和 Serverless 三者共同演繹不一樣層次的封裝和向上屏蔽下面的細節。Kubernetes 引入了不一樣的設計模式,實現對各類雲資源全新、有效和優雅的抽象和管理模式,讓集羣的管理和應用發佈變成了件至關輕鬆且不易出錯的事。被普遍採用的微服務軟件架構將分佈式應用的各類複雜度遷移到了服務之間,如何經過全局一致、體系化、規範化和無侵入的手段進行治理就變成了微服務軟件架構下相當重要的內容。Kubernetes 細化的應用程序的分解粒度,同時將服務發現、配置管理、負載均衡和健康檢查等做爲基礎設施的功能,簡化了應用程序的開發。而 Kubernetes 這種聲明式配置尤爲適合 CI/CD 流程,何況如今還有如 Helm、Draft、Spinnaker、Skaffold 等開源工具能夠幫助咱們發佈 Kuberentes 應用。
Service Mesh 經過將各服務所共用和與環境相關的內容剝離到部署於每一個服務邊上的 Sidecar 進程而輕鬆地作到了。這一剝離動做使得服務與平臺能充分解耦而方便各自演進與發展,也使得服務變輕而有助於改善服務啓停的及時性。Service Mesh 由於將那些服務治理相關的邏輯剝離到了 Sidecar 中且做爲獨立進程,因此 Sidecar 所實現的功能自然地支持多語言,爲上面的服務採用多語言開發創造了更爲有利的條件。經過 Service Mesh 對整個網絡的服務流量進行技術收口,讓異地多活這樣涉及流量調度的系統工程實現起來更加優雅、簡潔與有效,也能更加方便地實現服務版本升級時的灰度、回滾而改善安全生產質量。因爲技術收口,給服務流量的治理和演進、排錯、日誌採集的經濟性等疑難問題創造了新的發展空間。
您能夠經過如下導航來在 Gitbook 中閱讀筆者的系列文章,涵蓋了技術資料概括、編程語言與理論、Web 與大前端、服務端開發與基礎架構、雲計算與大數據、數據科學與人工智能、產品設計等多個領域:
此外,你還可前往 xCompass 交互式地檢索、查找須要的文章/連接/書籍/課程;或者在 MATRIX 文章與代碼索引矩陣中查看文章與項目源代碼等更詳細的目錄導航信息。最後,你也能夠關注微信公衆號:『某熊的技術之路』以獲取最新資訊。