1. 程式人生 > >俯瞰 Java 服務端開發

俯瞰 Java 服務端開發

原文首發於 [github](https://github.com/lcomplete/TechShare) ,歡迎 star 。 > Java 服務端開發是一個非常寬廣的領域,要概括其全貌,即使是幾本書也講不完,該文將會提到許多的技術及工具,但不會深入去講解,旨在以一個俯瞰的視角去探尋這片領域。 ## 目錄 - [目錄](#目錄) - [框架](#框架) - [Spring Boot](#spring-boot) - [Vert.x](#vertx) - [網路](#網路) - [五層協議](#五層協議) - [HTTP 協議](#http-協議) - [TCP 擁塞控制](#tcp-擁塞控制) - [網路 I/O 模型](#網路-io-模型) - [資料庫](#資料庫) - [關係型資料庫](#關係型資料庫) - [儲存引擎](#儲存引擎) - [NewSQL](#newsql) - [NoSQL 資料庫](#nosql-資料庫) - [時序資料庫](#時序資料庫) - [列式資料庫](#列式資料庫) - [嵌入式資料庫](#嵌入式資料庫) - [中介軟體](#中介軟體) - [Web Server](#web-server) - [分散式快取](#分散式快取) - [KV 儲存](#kv-儲存) - [訊息佇列](#訊息佇列) - [定時排程](#定時排程) - [RPC](#rpc) - [資料庫中介軟體](#資料庫中介軟體) - [日誌系統](#日誌系統) - [配置中心](#配置中心) - [微服務](#微服務) - [服務註冊與發現](#服務註冊與發現) - [熔斷與降級](#熔斷與降級) - [鏈路追蹤 / APM](#鏈路追蹤--apm) - [API 閘道器](#api-閘道器) - [服務網格](#服務網格) - [常用開源元件](#常用開源元件) - [資料訪問](#資料訪問) - [工具元件](#工具元件) - [快取](#快取) - [位元組碼修改](#位元組碼修改) - [http客戶端](#http客戶端) - [響應式程式設計](#響應式程式設計) - [序列化](#序列化) - [分散式事務](#分散式事務) - [事件驅動框架](#事件驅動框架) - [規則引擎](#規則引擎) - [測試](#測試) - [程式設計思想](#程式設計思想) - [原則](#原則) - [結語](#結語)
## 框架 ### Spring Boot Spring 框架已經成為 Java 服務端開發領域裡的標配,無數的服務基於其開發,它整合了服務端開發所需的絕大多陣列件,Spring Boot 在其基礎上又做了一層輕封裝並簡化了依賴管理,使得它用起來更加的便捷。 ### Vert.x Spring 框架早已成為主流,但是我們也不能忽略了其他優秀框架的存在。 [Vert.x](https://github.com/vert-x3) 是在 JVM 基礎上構建響應式應用的一套工具集,支援多種語言,它不僅是一套工具集,也可視作是一套框架,其中包含使用 Netty 編寫的 Web 框架、gprc、redis 客戶端等眾多元件,囊括了大部分開發網路應用時所需用到的元件,它最重要的核心概念是使用了事件驅動的非阻塞模型,因此具備高度的可伸縮性。它使用了響應式的程式設計模型,這個話題在下文中會再提到。 ## 網路 ### 五層協議 學習計算機網路時一般採用折中的辦法,也就是中和 OSI 和 TCP/IP 的優點,採用一種只有五層協議的體系結構,即物理層、資料鏈路層、網路層、運輸層、應用層,每一層都有其各自的術語,比如:吞吐量、子網掩碼、VIP、DNS等等,這在平時工作的溝通過程中也是至關重要。要做好服務端程式設計,我們必須對網路的一些基本概念有一個清晰的認識,推薦閱讀《計算機網路:自頂向下方法》。 推薦閱讀: * [五層協議](https://github.com/Snailclimb/JavaGuide/blob/master/docs/network/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C.md) * [計算機網路知識總結](https://github.com/Snailclimb/JavaGuide/blob/master/docs/network/%E5%B9%B2%E8%B4%A7%EF%BC%9A%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E7%9F%A5%E8%AF%86%E6%80%BB%E7%BB%93.md) ### HTTP 協議 對於服務端程式設計而言,在網路這個部分最重要的還是 HTTP 協議,從 TCP、DNS ,最後到瀏覽器響應,我們必須清楚整個過程是如何運轉的,中間再加入 CDN、反向代理、流量控制等服務時,其會更加複雜,但也正因為網路的分層模型,使得我們可以在這個中間過程中對服務端的響應效能做出優化。 具體到 HTTP 協議,其承載於 TCP 協議之上,中間再加上 TSL 或 SSL,就成了 HTTPS ,協議頭如何解析,響應體如何傳送,搞清楚了這些,可以很容易地開發一個簡單的 HTTP 服務。HTTP 協議也在不斷改進,目前已經到了 2.0 版本,在傳輸效能上有大幅的提升。 HTTP 使用明文傳輸,因此很容易受到中間人攻擊,可以在路由器、代理等多個層面截獲傳輸資訊,因此 HTTP 終將退出歷史舞臺,HTTPS 必然成為主流,但是 HTTPS 也並非絕對安全,由於證書籤發機構存在安全漏洞,曾導致許多網站使用了不安全的 SSL 證書,因此很多應用會採用自定義的加密方式來加強資訊傳輸的安全性。 ### TCP 擁塞控制 TCP 使用多種擁塞控制策略來避免傳送方至接收方之間的鏈路變得擁塞,其有許多具體的實現演算法,具體的實現細節隱藏在作業系統的核心當中,通過使用不同的演算法,可以在不同的場景下獲得最佳的效能,例如 Google 設計併發布的 BBR(Bottleneck Bandwidth and Round-trip propagation time)擁塞演算法,它能更有效地利用網路環境,尤其在超遠距離的網路傳輸中能獲得更大的效能提升,目前已經移植到 linux 核心4.9版本。 由於許多網路層相關的演算法都隱藏在作業系統核心當中,普通計算機使用者一般無需理解這些概念,但是對於服務端開發者來說,若對其有一定的瞭解,則能夠從這一層面尋找解決方案來提升系統的吞吐量。 ### 網路 I/O 模型 常見 I/O 模型主要有 BIO(阻塞I/O),NIO(非阻塞I/O),I/O複用、事件(訊號)驅動I/O、AIO(非同步I/O)。以讀取資料為例,傳統的 BIO 裡面呼叫 socket 的 read 方法,函式在收到資料前會一直阻塞,對於 NIO,如果有資料則返回,反之返回 0,不會發生阻塞,而 AIO 則更進一步,不光等待資料就緒是非阻塞,連資料從網絡卡到記憶體的過程也是非同步的。 結合使用 NIO、AIO、I/O複用,可以解決執行緒瓶頸並處理海量連線,比如 nginx 使用了 AIO 模型,因此效能比 apache http server 效能更好。在 Java 領域,Netty 基於 Reactor 模式實現了一個非同步事件驅動的 NIO 框架,其已經運用在網際網路的許多領域,大到大資料、通訊行業、遊戲行業,小到 redis 客戶端、Web 框架等開源元件都有其身影。 ## 資料庫 ### 關係型資料庫 MySQL 是最流行的開源資料庫,PostgreSQL 是最高階的開源資料庫,SQL Server 是微軟開發的企業級資料庫,還有在大型公司用的較多的 Oracle 資料庫。在服務端開發方面,MySQL 的市場佔用率是最高的,但也推薦學習一下 PostgreSQL 和所謂的「企業級資料庫」,畢竟 MySQL 在這些資料庫面前有時確實顯得功能簡單、實用性不足。 在真實的工作中,資料庫的設計是一個非常需要平衡取捨的過程,有時為了優化查詢效能不得不做一些資料冗餘,而在資料量極大的情況下,又必須謹慎選擇每一列的儲存型別、避免冗餘。 資料量非常大的情況下,大多數時候還要進行分庫分表的設計。 - ShardingSphere - 目前 Java 中主流的分庫分表中介軟體,支援客戶端架構、代理架構,Sidecar 架構目前還在開發中。 - Vitess - Vitess 是 Youtube 開源的 MySQL 資料庫集群系統,採用的是中心化的資料庫代理架構,這套資料叢集承載了 Youtube 數以億計的資料量和訪問請求。 ### 儲存引擎 MySQL 中主流使用的是 InnoDB 儲存引擎,內部採用了 B+ 樹的索引結構,Percona XtraDB 是InnoDB 儲存引擎的增強版,Percona 相容 MySQL,號稱擁有更好的效能,也具有一定的市場佔有率。 除了 InnoDB 及其衍生引擎,RocksDB 也是一個可選項,這是一個 LSM 儲存引擎,不同於傳統的基於 B+ 樹的儲存引擎,基於 LSM 儲存引擎的資料庫尤其適合寫多讀少的場景,由於最初是設計用來做持久化的鍵值資料儲存,因此在 KV 儲存上具有非常高的效能,可惜的是 MySQL 無法選擇 RocksDB 作為儲存引擎,目前支援的資料庫有 MariaDB 和 Percona。 ### NewSQL NewSQL 這一新興領域也大量使用了 RocksDB 作為儲存引擎,TiDB 作為流行度較高的 NewSQL 產品,就是用其實現的資料持久化。 ### NoSQL 資料庫 - MongoDB - MongoDB 介於關係資料庫和非關係資料庫之間,不要求資料儲存具有固定的模式,且能用於儲存超大規模的資料集。 ### 時序資料庫 隨著網際網路的深入,應用場景越來越豐富,諸如系統執行狀態、系統指標採集等場景產生大量的資料,這類基於時間的一系列資料,以寫多讀少、資料量極大為特點,傳統的資料庫已經不適合儲存這類資料,時序資料庫由此誕生。 主流的時序資料庫有: - influxdb - Prometheus - graphite ### 列式資料庫 傳統的關係型資料庫採用行式儲存,大資料領域多采用列式儲存,列式儲存的主要優勢在於可以按需所取,在並行處理和資料壓縮上更有優勢。關係型資料庫適合 OLTP, 列式資料庫更適合 OLAP,為了使列式資料庫能更好地支援 OLTP,目前出現了像 kudu 和 Druid 這類優秀的開源產品,它們結合了列式儲存的優勢,並在 OLTP 方面也做了特別的優化。 主流的列式資料庫有: - HBase - Cassandra - kudu - Druid ### 嵌入式資料庫 傳統的關係型資料庫能夠支援企業級的應用,但在許多場景下,我們可能只需要一個小型應用,這個時候使用嵌入式資料庫是一個方便的選擇,除此之外,嵌入式資料庫非常適合用於做單元測試。 Java 中流行的嵌入式資料庫有: - h2base - moby ## 中介軟體 ### Web Server - Nginx - Nginx 使用 AIO 的模型實現高併發,Apache 每個請求獨佔一個執行緒。 - AIO 模型適合於 IO 密集型服務,多程序或執行緒適合於 CPU 密集型服務,由於大多數 Web 服務都屬於 IO 密集型,nginx 的市場佔有率逐漸超過了 Apache。由於這一特點,Nginx 也非常適合做反向代理,通過這種機制做負載均衡也是非常主流的一種方案。 - tomcat、jetty、weblogic 等傳統 Java Web 伺服器 - 隨著容器化技術的流行,這類伺服器日漸式微,市場佔有率逐漸下降,進行容器化部署時tomcat一般內建在程式中,這種進步使得開發者可以更關注業務程式碼本身,而無需關注此類伺服器的種種細節,可謂是對開發人員的減負。 - OpenResty - 優秀的開源產品經常出現許多優秀的衍生產品,比如 Percona 之於 MySQL,OpenResty 之於 Nginx,Kong 之於 OpenResty。 - Nginx 市場佔有率之高,但許多場景下是用其做反向代理,OpenResty 的設計目標則是讓 Web 服務直接跑在 Nginx 服務內部。 - OpenResty 同時也是基於 LuaJIT 的 Web 平臺,開發者可以很方便地使用 Lua 呼叫 Nignx 模組,具有強大的可擴充套件性,比如可將典型的 Nginx + Tomcat + MySQL 架構更換為 Nginx + Lua + Redis + Tomcat + MySQL 的架構。 - Kong 從技術上講也屬於 Web Server,但一般用來做 API 閘道器,下文中再詳述。 ### 分散式快取 - Redis - Redis 作為一個高效能的記憶體資料庫,目前已被廣泛使用,其支援多種資料結構,根據不同場景使用不同的資料結構,才能最有效地使用它。 ### KV 儲存 - Pika - Redis 的效能非常高,但在將其做資料庫使用時存在資料持久化的問題,Pika 就是為了解決這一問題而出現,它底層基於 RocksDB,修改了其部分原始碼,在 KV 資料持久化上有非常高的效能,與基於記憶體的 redis 相比僅有較小的效能下降,同時它還相容大部分的 redis 協議,與 Redis 的使用幾乎沒有差異,上手簡單。 - Tair - Tair 與 Pika 類似,底層支援多種儲存引擎,包括 mdb、rdb、ldb,其中 ldb 基於 leveldb(google開源,rocksdb 在其基礎上優化),它可將記憶體儲存和持久化相結合,具有高可用的分散式架構,目前開源版本已經不再維護,阿里雲上則提供了企業級的 Tair 儲存服務。 - SSDB - SSDB 也是相容 Redis 的一款 KV 資料庫,目前更新頻率較低,相比而言 Pika 目前還在更新中,且有企業進行背書。 ### 訊息佇列 訊息佇列在請求削峰、跨系統間通訊解耦、釋出訂閱等許多場景下都會使用到,不光能解決這些問題,採用訊息驅動的架構可以增強系統的擴充套件性,比如新增一個訂閱方,即可以實現新的功能,並且對當前的系統沒有任何的侵入性。 常用的訊息佇列產品有 kafka、rabbitmq 等,它們各有優缺點,在大資料領域 kafka 佔有絕對優勢,總體的市場佔有率也較高,而 rabbitmq 由於產品成熟,也被廣泛使用。 在使用訊息佇列的過程中,需要處理一系列的細節,比如:定義訊息處理者、如何傳送訊息、如何釋出事件、訊息如何序列化、如何記錄訊息記錄、設計訊息路由、訊息處理失敗的重試機制、訊息 id 等等,在具體的編碼過程中不能完全專注於業務程式碼開發,因此市面上有一些 ESB 產品在內部處理好了這些細節,並從更高的抽象層級提供更加簡潔的 API,在開發過程中則能更加聚焦在業務邏輯本身,當我們的系統面臨這些問題的時候,不妨選擇一個 ESB 產品來提升研發效率。 ### 定時排程 簡單的定時任務可以採用 linux cron 進行配置,複雜的場景也可以使用分散式任務排程框架,可選的實現方式非常多,這裡簡單的列舉幾種。 - Quartz - 老牌任務排程系統,許多分散式任務排程框架基於它而擴充套件。 - Spring Scheduler - 用它來做簡單的任務排程非常方便,但要注意由於現在的系統大多采用分散式部署,因此當使用它來做任務排程時最好做到單獨的服務中,避免與其他系統耦合。 - 國產分散式任務排程系統 - 目前較為流行的有 Elastic-Job、XXL-JOB,Elastic-Job 採用去中心化的架構,依賴 zookeeper 儲存任務排程資料,XXL-JOB 採用中心化排程的架構,排程採用 RPC 方式。 - PowerJob 是新興的一個開源任務排程系統,在功能上更為強大,支援 MapReduce 分片,值得關注。 ### RPC 提到 RPC 不得不提到日暮西山的 Web Service,其採用 XML 作為訊息格式,並以 SOAP 協議進行封裝,由於過於複雜且效能開銷較大,其逐漸被採用 JSON 格式的 REST 服務所取代,相比之下,REST 簡單且採用更高效的序列化方式,所以目前許多系統廣泛採用 HTTP 的方式進行遠端過程呼叫。 在對於效能要求特別高的場景,或從整體架構上考慮,人們才會選用專門的 RPC 產品,這類系統一般擁有更高效的通訊協議和資料傳輸格式,典型的有 dubbo、grpc、thrift,其中 grpc 具有最優秀的效能。 RPC 框架的原理其實與 HTTP 呼叫類似,只是採用了更精簡的協議頭和資料序列化方式,此外在服務註冊發現及負載均衡上也做了專門的封裝。在 Spring Cloud 中,使用 OpenFeign 進行服務間呼叫是非常方便的一個選擇,其使用 HTTP 方式,當效能無法滿足時,可考慮替換序列化方式,或選用 grpc 進行通訊。 ### 資料庫中介軟體 資料庫本身就是一個龐大的產品,除了前面提到的 ShardingSphere、Vitess 這類中介軟體,還有一類專門做資料處理的中介軟體。 - otter - 分散式資料庫同步系統,支援 MySQL、Oracle。 - canal - 基於 MySQL 資料庫增量日誌解析,提供增量資料訂閱和消費。 - DataX-Web - 分散式資料同步工具,可用來簡化 ETL 工作。 - gh-ost - 對資料表結構進行架構變更時,可能導致表被鎖住,如果資料量特別大,這種問題對於線上釋出的影響是比較大的,可以採用建新表並遷移資料再修改表名的方式手工處理,這種方式容易出錯且耗時,Github 開源的 MySQL 線上架構遷移工具則是程式化完成這一類操作的很好的選擇。 ### 日誌系統 - ELK - 日誌系統一般採用 ELK 技術棧,這其中包含三個子系統,因此要擴充套件一個新功能,可以有多種方式切入,比如做監控報警,可以使用 logstash 將 metrics 寫入到 Prometheus,也可以使用 kibana 上的 sentinl 外掛或者 ElastAlert 外掛。 - logstash 支援從許多管道收集資料,其中包括 kafka,在日誌量特別大的情況下,可以將日誌先發送至 kafka。 - Sentry - 日誌在很大一部分場景下都是用於排查錯誤的,除了 ELK 外還有專注於應用程式錯誤報告的系統,比如 Sentry。 ### 配置中心 由於越來越多的系統基於 docker 部署,配置中心不僅可以簡化系統的配置管理,也可簡化系統的釋出流程,目前較為流行的開源配置中心是 Apollo。另外也可以通過 zookeeper、Consul 等工具來實現統一配置管理。 Nacos 是阿里開源的一款集配置中心和註冊中心於一體的系統,使用它來做配置中心也較為方便,服務端部署相比 Apollo 簡化了許多。 ## 微服務 由於單體應用牽一髮而動全身的特點,許多大型應用在開發時都會自覺拆分為多個子系統,這是在微服務概念提出前就被廣泛採用的方式,而微服務概念的提出則更進一步,提出了一種全新的系統開發方式,使系統可以方便地拆分到更小的粒度,即微型服務,那麼在服務數量越來越多的情況下,服務治理、熔斷降級、鏈路追蹤等問題也浮出水面,於是解決這些問題的 Spring Cloud 框架冉冉升起。 ### 服務註冊與發現 主流的服務註冊與發現元件有:Eureka、Consul、Nacos 等等,它們採用不同的 CAP 分散式一致性規則或多種都支援,但不管使用哪一種,其實還是存在服務失聯的問題,比如在滾動更新的過程中,註冊中心未能及時剔除掉服務,導致呼叫方仍在呼叫停止的服務,首先我們可以通過調整配置減少更新週期,必要時需要修改其原始碼,使用長連線,只要連線中斷即從註冊中心剔除服務,具體的細節需要專門寫一篇文章來講解。 在可能的情況下,儘量使用訊息機制來進行服務間通訊,這是一個更好的選擇,除了更好地進行解耦,在滾動更新這個部分也能更好地保持系統不間斷運轉。 ### 熔斷與降級 服務間的呼叫過多,一定程度上增加了系統的耦合度,當其他微服務出問題或響應較慢時,整個系統都受影響,在必要時需要對出問題的服務進行熔斷或降級。 - Hystrix - Spring Cloud 框架預設整合的熔斷元件。 - Sentinel - Spring Cloud Alibaba 中整合的熔斷元件,提供了一個外部控制檯,可以實時調整系統的熔斷降級配置,在這個部分強於 Hystrix 。 ### 鏈路追蹤 / APM 服務間互相呼叫,使得除錯變得比單體應用複雜不少,這個時候使用鏈路追蹤工具能夠簡化除錯,同時也能夠對應用程式的效能有更直觀的監控。 主流的鏈路追蹤元件有: - zipkin - pinpoint - SkyWalking - jaeger ### API 閘道器 Spring Cloud 體系中常用的閘道器前有 Zuul,後有 Gateway,這一類跟 Spring Cloud 結合緊密,使用方便,但由於它們都是 Java 寫成,在許多場景下還是比不上一些專門的閘道器產品。 - Kong - Kong 是 OpenResty 的衍生開源閘道器產品,擁有優秀的效能和豐富的外掛,可滿足許多的擴充套件性需求。 - Traefik - Traefik 是用 Go 語言編寫的閘道器,定位是雲原生的邊界路由閘道器產品,它擁有豐富的特性、易用的控制面板,與雲原生場景深度結合,提供了實時的流量指標可對接到 Prometheus 中。其企業版包含限流、高可用等特性,開源版在這一部分有所缺失。 ### 服務網格 從單體應用到微服務的演進,我們會發現服務治理、熔斷、Tracing 這些幾乎是必不可少的部分,即使是使用 Spring Cloud 框架,我們也需要關注大量的微服務技術細節,為了分離這一關注點並使這些技術成為基礎設施一般的存在,服務網格應運而生。 [什麼是Service Mesh(服務網格)?](https://jimmysong.io/blog/what-is-a-service-mesh/) >
服務網格好比微服務間的 TCP/IP,負責服務之間的網路呼叫、限流、熔斷和監控。對於編寫應用程式來說一般無須關心 TCP/IP 這一層(比如通過 HTTP 協議的 RESTful 應用),同樣使用 Service Mesh 也就無須關心服務之間的那些原本通過服務框架實現的事情,比如 Spring Cloud、Netflix OSS 和其他中介軟體,現在只要交給 Service Mesh 就可以了。 目前主流的服務網格有: - Istio - Linkerd ## 常用開源元件 上文有提及的,這裡不再累述。 ### 資料訪問 - MyBatis Plus - Mapper - jOOQ - JPA - dynamic-datasource-spring-boot-starter - sharding-jdbc ### 工具元件 - guava - commons-lang3 - hutool ### 快取 - redission - jetcache - caffeine ### 位元組碼修改 - asm - javassist - cglib ### http客戶端 - okhttp - Aache HttpClient - retrofit - openfeign ### 響應式程式設計 - RxJava - reactor-core ### 序列化 - protobuf - protostuff - hessian ### 分散式事務 - seata ### 事件驅動框架 - AxonFramework ### 規則引擎 - drools ### 測試 - junit - mockito - Spock ## 程式設計思想 程式設計思想是一個抽象的概念,要將其具象化我們必須透過現象看其本質,優秀的程式設計思想是對各種優秀想法的組織,這些想法可以精煉成許多原則,原則是構成程式設計思想的一個重要部分,也是所有程式設計方式都可以遵守的通用準則。在原則的基礎上,在編碼過程中反覆解決的一些問題又被歸納為模式,這兩者是思想的主要構成,另外也有不同的程式設計正規化及方法論,我在這裡簡單的講一下設計原則。 ### 原則 >
很多原則不僅適用於程式設計領域,也適用於其他領域,我想這也是為什麼喬布斯提倡人人都應該學習程式設計,因為它能讓你擁有更好的思考方式。 - 保持簡單 - Keep It Simple, Stupid (KISS) - 最重要的原則之一,可靠來源於簡單,只有不斷保持系統的簡單、程式碼的簡單,才能更好地創造優秀的軟體。 - You Ain’t Gonna Need It (YAGNI) - 如無必要,勿增複雜性,避免過度設計。 - Separation of Concerns (SoC) – 關注點分離 - 將目標相關聯的部分封裝在一起,標識為關注點。這是降低複雜性的一個重要原則,MVC 或 MVP 模式都是該原則的應用,將模型、檢視和控制器作為不同的關注點,使得每一個關注點可以更有效地理解及重用。 - 在編碼過程中,也可以應用這一思想,比如我們首先關注應用程式是否可用,當其執行正確後再關心執行效率,這比同時進行這兩項工作要簡單的多。 - 不要重複 - Don’t Repeat Yourself (DRY) - 最簡單也最容易理解的原則,每個程式設計師都應該以隨意複製貼上程式碼而感到羞愧。 - Convention over Configuration(CoC)- 慣例優於配置原則 - 將約定的配置方式和資訊作為預設的規則來使用,可以減少開發人員做決定的數量,減少編碼量,獲得簡單的好處,又不會丟失靈活性。 - Spring Boot 框架解決的問題之一就是簡化專案的配置,其大量應用了 CoC 原則。 - S.O.L.I.D 原則 - Single Responsibility Principle (SRP) - 單一職責原則 - 一個類,只做一件事,並把這件事做好,其只有一個引起它變化的原因。 - 很簡單的原則,但是很多程式設計師在工作時經常違反這一原則,比如一個 service 類中引入許多 dao 物件,提供多種不相關服務。 - Open/Closed Principle (OCP) – 開閉原則 - 模組是可擴充套件的,而不可修改的。也就是說,對擴充套件是開放的,而對修改是封閉的。 - 設計模式中的代理、策略和觀察者模式比較好地實現了這一原則。 - 當我們定義的一個API可接受函式作為引數時,實際上也是一種策略模式的變體,同樣也體現了這一原則。 - Liskov substitution principle (LSP) – 里氏代換原則 - 子類必須能夠替換成它們的基類。 - 這個原則可作為我們設計類繼承關係的基準。 - Interface Segregation Principle (ISP) – 介面隔離原則 - 對介面進行拆分,使用多個專門的介面比使用單一的總介面要好。 - 介面可以多繼承,那為何要因為懶惰而將其隨便定義在一個總接口裡呢? - Dependency Inversion Principle (DIP) – 依賴倒置原則 - 高層模組不應該依賴於低層模組的實現,而是依賴於高層抽象。 - IoC 是 DIP 的一個具體實現,其已經深入到程式語言當中,Spring 框架最初就只是作為一個 IoC 容器,而後才不斷擴展出許多實用功能並最終成為一個開發框架。 - 相關原則:Hollywood Principle – 好萊塢原則(所有的元件都是被動的,所有的元件初始化和呼叫都由容器負責)。 - 高內聚、低耦合 - Law of Demeter – 迪米特法則 - 又稱“最少知識原則”(Principle of Least Knowledge),一個類對於其他類知道的越少越好,知道的越多其耦合程度就越高。 - 門面模式和中介模式都是迪米特法則應用的例子。 - 這一原則強調低耦合。 - Common Closure Principle(CCP)– 共同封閉原則 - 如果必須修改應用程式裡的程式碼,我們希望所有的修改都發生在一個包裡(修改關閉),而不是遍佈在很多包裡。 - 在微服務架構中,若修改一個功能時,經常需要修改多個服務,那麼其很有可能違反了 CCP 原則不恰當地進行了服務拆分。 - 這一原則強調高內聚。 - Common Reuse Principle (CRP) – 共同重用原則 - 包的所有類被一起重用,沒有被一起重用的類不應該被組合在一起。依賴一個包就是依賴這個包所包含的一切。 - CCP則讓系統的維護者受益,CCP讓包儘可能大(CCP原則加入功能相關的類),CRP則讓包儘可能小(CRP原則剔除不使用的類)。它們的出發點不一樣,但不相互衝突。 - 這一原則同樣強調高內聚。 ## 結語 正如開頭所言,服務端開發領域極其龐大,本文還有許多枝節尚未提及,比如安全、DevOps等等。技術的演進使這個領域加速擴大,未來還會有許多的變化,也許 Service Mesh 將會成為主流,也許 NewSql 將成為開發標配,任何一門技術的演進歷史變長,它的總體學習時間相應也會增加,但這並不意味著對其的應用也會變得複雜,我們不能忽視雲端計算這一因素,雲服務的提供為開發者隱藏了許多的細節,在這個時代不需要知曉每一項技術的原理,也能夠開發出服務千萬使用者的產品。 未來會演進成什麼樣,可以去期待,但不要只是去期待,因為未來已經到來,只是還沒有平均