您好,登錄后才能下訂單哦!
本部分節選自《軟件架構設計》
軟件開發就是把一個復雜的問題分解為一系列簡單的問題,再把一系列簡單的解決方案組合成一個復雜的解決方案。而軟件開發中最大的挑戰,就是即能夠快速高效地針對需求、環境的變化做出改變,也能夠持續提供穩定、高可用的服務。而軟件架構,就是軟件系統的骨骼與框架。
所謂架構,見仁見智,很難有一個明確或標準的定義;但架構并非鏡花水月或陽春白雪,有系統的地方就需要架構,大到航空飛機,小到一個電商系統里面的一個功能組件,都需要設計和架構。抽象而言,架構就是對系統中的實體以及實體之間的關系所進行的抽象描述,是對物/信息的功能與形式元素之間的對應情況所做的分配,是對元素之間的關系以及元素同周邊環境之間的關系所做的定義。架構能將目標系統按某個原則進行切分,切分的原則,是要便于不同的角色進行并行工作,結構良好的創造活動要優于毫無結構的創造活動。
軟件架構的核心價值,即是控制系統的復雜性,將核心業務邏輯和技術細節的分離與解耦。軟件架構是系統的草圖,它描述的對象是直接構成系統的抽象組件;各個組件之間的連接則明確和相對細致地描述組件之間的通信。在實現階段,這些抽象組件被細化為實際的組件,比如具體某個類或者對象。在面向對象領域中,組件之間的連接通常用接口來實現。架構師的職責是努力訓練自己的思維,用它去理解復雜的系統,通過合理的分解和抽象,理解并解析需求,創建有用的模型,確認、細化并擴展模型,管理架構;能夠進行系統分解形成整體架構,能夠正確的技術選型,能夠制定技術規格說明并有效推動實施落地。
在筆者的知識體系中,實際上將架構分為業務架構、應用架構、云基礎架構這幾大類,業務架構主要著眼于控制業務的復雜性,基礎架構著眼于解決分布式系統中存在的一系列問題。無論何種架構,都希望能實現系統的可變的同時保障業務的高可用。另一個層面,根據企業中職責的劃分,我們往往可以將軟件架構,及關聯的架構師劃分為以下幾類:
業務架構/解決方案架構:核心是解決業務帶來的系統復雜性,了解客戶/業務方的痛點,項目定義,現有環境;梳理高階需求和非功能性需求,進行問題域劃分與領域建模等工作;溝通,方案建議,多次迭代,交付總體架構。
應用架構:根據業務場景的需要,設計應用的層次結構,制定應用規范、定義接口和數據交互協議等。并盡量將應用的復雜度控制在一個可以接受的水平,從而在快速的支撐業務發展的同時,在保證系統的可用性和可維護性的同時,確保應用滿足非功能屬性要求(性能、安全、穩定性等)。
數據架構:專注于構建數據中臺,統一數據定義規范,標準化數據表達,形成有效易維護的數據資產。打造統一的大數據處理平臺,包括數據可視化運營平臺、數據共享平臺、數據權限管理平臺等。
中間件架構:專注于中間件系統的構建,需要解決服務器負載,分布式服務的注冊和發現,消息系統,緩存系統,分布式數據庫等問題,同時架構師要在 CAP 之間進行權衡。
運維架構:負責運維系統的規劃、選型、部署上線,建立規范化的運維體系。
軟件架構設計的一個核心問題是能否使用重復的架構模式,即能否達到架構級的軟件重用。也就是說,能否在不同的軟件系統中,使用同一架構。當我們討論軟件架構時,常常會提及軟件架構模式(Architectural Pattern)與軟件架構風格(Architectural Style)。
軟件架構模式往往會用于具體地解決某個具體的重復的架構問題,而架構風格則是對于某個具體的架構設計方案的命名。軟件架構風格是描述某一特定應用領域中系統組織方式的慣用模式;架構風格反映了領域中眾多系統所共有的結構和語義特性,并指導如何將各個模塊和子系統有效組織成一個完整的系統。
在筆者的系列文章中,CRUD、分層架構、六邊形架構、洋蔥架構、REST 以及 DDD,都算是架構風格;而 CQRS、EDA、UDLA、微服務等則被劃分到架構模式中。
在軟件開發中,程序員往往能夠脫離現實規律的束縛,創造出天馬行空的世界,其也是最具有創造力的活動之一。編程唯一需要的是創造力思維和思維組織能力,這意味著在軟件開發過程中最大限制是理解我們正在創建的對象。隨著軟件的演進,加入更多的功能點,系統變得越來越復雜:各個模塊(Module)間存在著各種微妙的依賴關系。系統的復雜性隨著時間積累,對于程序員來說,修改系統時考慮周全所有的的相關因素變得越來越困難。這就會使軟件開放進度變緩慢,并且引入 Bug,而導致會進一步延緩開發進度,增加開發成本。在任何一個系統的生命周期中,復雜性不可避免會增加;系統越大,需要更多的人開發,管理系統復雜性的工作就越困難。
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)轉化為領域概念清晰的顯性化表達出來。
統一語言,軟件的開發人員/使用人員都使用同一套語言,即對某個概念,名詞的認知是統一的,建立清晰的業務模型,形成統一的業務語義。將模型作為語言的支柱。確保團隊在內部的所有交流中,代碼中,畫圖,寫東西,特別是講話的時候都要使用這種語言。例如賬號,轉賬,透支策略,這些都是非常重要的領域概念,如果這些命名都和我們日常討論以及 PRD 中的描述保持一致,將會極大提升代碼的可讀性,減少認知成本。。比如不再會有人在會議中對“工單”、“審核單”、“表單”而反復確認含義了,DDD 的模型建立不會被 DB 所綁架。
面向領域,業務語義顯性化,以領域去思考問題,而不是模塊。將隱式的業務邏輯從一推 if-else 里面抽取出來,用通用語言去命名、去寫代碼、去擴展,讓其變成顯示概念;很多重要的業務概念,按照事務腳本的寫法,其含義完全淹沒在代碼邏輯中沒有突顯出來。
本部分節選自《微服務與云原生》
在 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。
Codeless 對應的是服務開發,實現了源代碼托管,你只需要關注你的代碼實現,而不需要關心你的代碼在哪,因為在整個開發過程中你都不會感受到代碼庫和代碼分支的存在。
Applicationless 對應的是服務發布,在服務化框架下,你的服務發布不再需要申請應用,也不需要關注你的應用在哪。
這些技術組合搭配,能夠構建容錯性好、易于管理和便于觀察的松耦合系統;再結合可靠的自動化手段,云原生技術能夠使工程師輕松地對系統作出頻繁和可預測的重大變更。由此可見,云原生是保障系統能力靈動性地有效抓手;云原生技術有利于各組織在公有云、私有云和混合云等新型動態環境中,構建和運行可彈性擴展的應用。微服務架構非常適合云原生應用程序;但是,云原生同樣存在著一定的限制,如果你的云原生應用程序部署在 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 與大前端、服務端開發與基礎架構、云計算與大數據、數據科學與人工智能、產品設計等多個領域:
知識體系:《Awesome Lists | CS 資料集錦》、《Awesome CheatSheets | 速學速查手冊》、《Awesome Interviews | 求職面試必備》、《Awesome RoadMaps | 程序員進階指南》、《Awesome MindMaps | 知識脈絡思維腦圖》、《Awesome-CS-Books | 開源書籍(.pdf)匯總》
編程語言:《編程語言理論》、《Java 實戰》、《JavaScript 實戰》、《Go 實戰》、《Python 實戰》、《Rust 實戰》
軟件工程、模式與架構:《編程范式與設計模式》、《數據結構與算法》、《軟件架構設計》、《整潔與重構》、《研發方式與工具》
Web 與大前端:《現代 Web 開發基礎與工程實踐》、《數據可視化》、《iOS》、《Android》、《混合開發與跨端應用》
服務端開發實踐與工程架構:《服務端基礎》、《微服務與云原生》、《測試與高可用保障》、《DevOps》、《Node》、《Spring》、《信息安全與***測試》
分布式基礎架構:《分布式系統》、《分布式計算》、《數據庫》、《網絡》、《虛擬化與編排》、《云計算與大數據》、《Linux 與操作系統》
數據科學,人工智能與深度學習:《數理統計》、《數據分析》、《機器學習》、《深度學習》、《自然語言處理》、《工具與工程化》、《行業應用》
產品設計與用戶體驗:《產品設計》、《交互體驗》、《項目管理》
此外,你還可前往 xCompass 交互式地檢索、查找需要的文章/鏈接/書籍/課程;或者在 MATRIX 文章與代碼索引矩陣中查看文章與項目源代碼等更詳細的目錄導航信息。最后,你也可以關注微信公眾號:『某熊的技術之路』以獲取最新資訊。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。