# 微服務

微服務就是一些協同工作的，小而自治的服務。

## 很小，專注做好一件事

隨着需求的迭代，新功能的增加，代碼庫往往會變得越來越大，儘管我們極力希望在巨大的代碼庫中做到清晰的模塊化，但事實上模塊與模塊之間的界限很難劃分得清楚，逐漸地相似的功能代碼在代碼庫中隨處可見，以致於在迭代時想要知道該在什麼地方做修改都很困難，修復 `Bug` 和增加新特性新功能越來越難。   
在一個單體系統中，通常會創建一些抽象層或者實現模塊化來保證代碼的 `內聚性`，從而避免上面提到的問題。

> 根據 Robert C. Martin 的一個對 [單一職責原則 (Single Responsibility Principle)](https://baike.baidu.com/item/單一職責原則/9456515) 的論述：“*把因為相同原因而變化的東西聚合到一起，把因為不同原因而變化的東西分離開來。*” 該論述很好地強調了內聚性這一概念。

微服務則將這一理念應用在獨立的服務上，根據業務的邊界確定服務的邊界，每個服務專注於服務邊界之內的事情，因為可以避免很多由於代碼庫過大衍生出來的各種問題。   
那麼一個微服務到底應該多微小？足夠小即可，不要過小。那麼怎麼衡量一個系統是否拆足夠小了呢？當你面對這個系統時，不會再有 "過大" 想要拆小它的慾望時，那麼它應該就足夠小了。服務越小，`微服務架構(Microservice)` 的優點和缺點也就越明顯，使用的服務越小，獨立性帶來的好處就越多，但管理大量的服務也會更加複雜。

## 自治性

一個微服務就是一個獨立的實體，它可以獨立被部署，也可以作為一個操作系統進程存在。服務與服務之間存在隔離性，服務之間均通過網絡調用進行通信，從而加強服務之間的隔離性，避免緊耦合。服務之間應該可以彼此獨立進行修改，並且某一個服務的部署不應該引起該 `服務消費方(Service Consumer)` 的變動。這就要求我們需要考慮這些 `服務提供方(Service Provider)` 什麼應該暴露，什麼應該隱藏，如果暴露得過多，那麼 `服務消費方(Service Consumer)` 會與該服務的內部實現產生耦合，這會使得服務直接產生額外的協調工作，從而降低了服務的自治性。

## 主要好處

### 技術的異構性

在一個由多個服務相互協作的系統中，可以在不同的服務中選用最適合該服務的技術，且由於服務間通過網絡調用，服務的實現不會受限於系統的實現語言或框架。也就意味着當系統中一部分需要做性能提升，可以使用性能更好的技術棧重新構建該部分的實現。

### 彈性

實現彈性系統的一個關鍵概念就是 `艙壁(Bulkhead)`，如果系統中的一個組件或一個服務不可用了，但並沒有導致級聯故障，那麼系統的其它部分還可以正常運行。微服務的 `服務邊界` 很顯然就是一個 `艙壁(Bulkhead)`，在 `單體架構(Monolithic architecture)` 系統中，也就是傳統的 `PHP-FPM` 架構下的系統中，如果某個部分不可用，那麼大部分情況是所有功能都不可用，雖然可以通過負載均衡等技術將系統部署在多個節點上面降低系統完全不可用的概率，但對於 `微服務架構(Microservice)` 系統而言，其架構本身就能夠很好地處理服務不可用和功能降級等問題。

### 擴展

一個 `單體架構(Monolithic architecture)` 的系統只能作為一個整體進行擴展，即使系統中只有一小部分存在性能問題。如果使用較小的多個服務，則可以只對需要擴展的服務進行擴展，這樣可以把那些不需要擴展的服務運行在更廉價的服務器上，節省成本。

### 簡化部署

在代碼量龐大的 `單體架構(Monolithic architecture)` 系統中，即使只修改了一行代碼，也需要重新部署整個系統才能夠發佈該變更，這種部署影響很大、風險很高，因此涉及到的干係人不敢輕易做部署，於是在實際的操作中部署的頻率就不變得很低，版本與版本之間會對系統做了很多的功能或 `Bugfix`，並一次性將大量的變更一次性發布到生產環境中去，但兩次發佈之間的差異越大，出錯的可能性就更大。   
當然在傳統的 `PHP-FPM` 架構下的開發中，我們可能不會存在這樣的問題，因為熱更新是一種天然的存在，但利弊是同時存在的。

### 與組織架構相匹配

在 `單體架構(Monolithic architecture)` 下，且團隊的結構也是 "分佈式" (異地) 的情況下，大量工程師的代碼提交導致的代碼衝突與異地的迭代溝通會使維護系統變得更加的複雜，我們都知道一個合適的團隊規模的人在一個小型的代碼庫上工作可獲得更高的生產力，那麼服務的拆分和歸屬便能很好的劃分相關的職責。

### 可組合性

`分佈式系統` 和 `面向服務架構(SOA)` 聲稱的主要好處是易於重用已有的功能，那麼在 `微服務架構(Microservice)` 下，更細粒度的服務拆分會將這一優點體現得更淋漓盡致。

### 可重構性高

如果您面對的是一個大型的 `單體架構(Monolithic architecture)` 系統，裏面的代碼混亂而醜陋，所有人都不敢輕易去重構它。但當你面對的是一個小規模的細粒度的服務時，重構一個服務甚至重寫一個對應的服務都是一件相對可操作的事情。在一個大型的 `單體架構(Monolithic architecture)` 系統一天刪除上百行代碼，您可以確信不會引發任何的問題嗎？但在良好的 `微服務架構(Microservice)` 下，我相信直接刪除一個服務您也可以遊刃有餘。

## 沒有銀彈 No Silver Bullet

雖然 `微服務架構(Microservice)` 好處眾多，但 **微服務不是銀彈 ！！！** ，您需要面對所有分佈式系統都需要面對的複雜性，你可能需要在部署、測試和監控上做很多的工作，在服務間調用、服務的可靠性上做很多工作，甚至您還需要處理類似於 分佈式事務 或者與 CAP 相關的問題。儘管 `Hyperf` 已經為您解決了許多的問題，但在實施 `微服務架構(Microservice)` 之前您的團隊必須儲備足夠的分佈式系統相關的知識體系，以面對很多您在 `單體架構(Monolithic architecture)` 下可能沒有面臨過甚至沒有考慮過的問題。


*| 本章節部分內容譯自 Sam Newman 的 《Building Microservices》*
