俯瞰 Java 服務端開發
阿新 • • 發佈:2020-09-28
原文首發於 [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 將成為開發標配,任何一門技術的演進歷史變長,它的總體學習時間相應也會增加,但這並不意味著對其的應用也會變得複雜,我們不能忽視雲端計算這一因素,雲服務的提供為開發者隱藏了許多的細節,在這個時代不需要知曉每一項技術的原理,也能夠開發出服務千萬使用者的產品。
未來會演進成什麼樣,可以去期待,但不要只是去期待,因為未來已經到來,只是還沒有平均