微服務

微服務（Microservices）是一種軟體架構風格，它是以專注於單一責任與功能的小型功能區塊 (Small Building Blocks) 為基礎，利用模組化的方式組合出複雜的大型應用程式，各功能區塊使用與語言無關 (Language Independent），而且複雜的服務背後是使用簡單 URI 來開放介面，任何服務，任何細粒都能被開放（exposed）。這個設計在 HP 的實驗室被實現，具有改變複雜軟體系統的強大力量。

2014年，Martin Fowler 與 James Lewis 共同提出了微服務的概念，定義了微服務是由以單一應用程式構成的小服務，自己擁有自己的進程與輕量化處理，服務依業務功能設計，以全自動的方式部署，與其他服務使用HTTP API通訊。同時服務會使用最小的規模的集中管理 (例如 Docker) 能力，服務可以用不同的程式語言與資料庫等元件實作。

## 概念

微服務的另一個對比是單體式應用程式。單體式應用表示一個應用程式內包含了所有需要的業務功能，並且使用像主從式架構（Client/Server）或是多層次架構（N-tier）實作，雖然它也是能以分散式應用程式來實作，但是在單體式應用內，每一個業務功能是不可分割的。若要對單體式應用進行擴展則必須將整個應用程式都放到新的運算資源（如：虛擬機器）內，但事實上應用程式中最耗費資源、需要運算資源的僅有某個業務部份（例如跑分析報表或是數學演演算法分析），但因為單體式應用無法分割該部份，因此無形中會有大量的資源浪費的現象。

微服務運用了以業務功能的設計概念，應用程式在設計時就能先以業務功能或流程設計先行分割，將各個業務功能都獨立實作成一個能自主執行的個體服務，然後再利用相同的協定將所有應用程式需要的服務都組合起來，形成一個應用程式。若需要針對特定業務功能進行擴充時，只要對該業務功能的服務進行擴展就好，不需要整個應用程式都擴展，同時，由於微服務是以業務功能導向的實作，因此不會受到應用程式的干擾，微服務的管理員可以視運算資源的需要來配置微服務到不同的運算資源內，或是佈建新的運算資源並將它配置進去。

雖然使用一般的伺服器虛擬化技術就能應用於微服務的管理，但容器技術 (Container Technology) 如 Docker 會更加地適合發展微服務的運算資源管理技術。

## 規劃

微服務的規劃與單體式應用程式十分不同，微服務中每個服務都需要避免與其他服務有所牽連，且都要能夠自主，並在其他服務發生錯誤時不受干擾。

### 資料庫

微服務理念中有數個資料庫的規劃方式。

- 每個服務都各有一個資料庫，同屬性的服務可共享同個資料庫。
- 所有服務都共享同個資料庫，但是不同表格，並且不會跨域存取。
- 每個服務都有自己的資料庫，就算是同屬性的服務也是，資料庫並不會共享。

資料庫並不會只存放該服務的資料，而是「該服務所會用到的所有資料」。更深層一點的舉例：假設有個文章服務，而這個服務可能會需要判斷使用者的帳號⋯⋯等。那麼文章服務的資料庫就可以放入使用者的部分資料。此舉是為了避免服務之間的相依性，避免文章服務呼叫使用者服務。

#### 資料庫的可棄性

實踐微服務有許多的做法，但其中一種做法是將資料庫作為短期的儲存空間而不是儲存長期的資料。這意味著資料庫可以在離線時被清空。因為它們可以在上線時從事件存儲中心恢復，因此也能以記憶體快取（如：Redis）作為資料庫伺服器。但這種做法需要將每個請求當作事件來進行廣播。如此一來就可以從事件存儲中心重播所有的事件來找回所有的資料。

### 溝通與事件廣播

微服務中最重要的就是每個服務的獨立與自主，因此服務與服務之間也不應該有所溝通。倘若真有溝通，也應採用異步溝通的方式來避免緊密的相依性問題。要達到此目的，則可用下列兩種方式：

#### 事件存儲中心（Event Store）

這可以讓你在服務叢集中廣播事件，並且在每個服務中監聽這些事件並作處理，這使得服務之間不需有緊密的相依性，而這些發生的事件都會被保存在事件存儲中心裡。這意味著當微服務重新上線、部署時可以重播（Replay）所有的事件。這也造就了微服務的資料庫隨時都可以被刪除、摧毀，且不需要從其他服務中取得資料。

### 服務探索

單個微服務在上線的時候，會向服務探索中心（如：Consul）註冊自己的 IP 位置、服務內容，如此一來就不需要向每個微服務表明自己的 IP 位置，也就不用替每個微服務單獨設定。當服務需要呼叫另一個服務的時候，會去詢問服務探索中心該服務的 IP 位置為何，得到位置後即可直接向目標服務呼叫。

這麼做的用意是可以統一集中所有服務的位置，就不會分散於每個微服務中，且服務探索中心可以每隔一段時間就向微服務進行健康檢查（如透過：TCP 呼叫、HTTP 呼叫、Ping），倘若該服務在時間內沒有回應，則將其從服務中心移除，避免其他微服務對一個無回應的服務進行呼叫。

## 內容

一個微服務架構的應用程式有下列特性：

- 每個服務都容易被取代。
- 服務是以能力來組織的，例如使用者介面、前端、推薦系統、帳單或是物流等。
- 由於功能被拆成多個服務，因此可以由不同的程式語言、資料庫實作。
- 架構是對稱而非分層（即生產者與消費者的關係）。

一個微服務架構：

- 適用於具持續交付（Continuous Delivery）的軟體開發流程。
- 與服務導向架構（Service-Oriented Architecture）不同，後者是整合各種業務的應用程式，但微服務只屬於一個應用程式。

## 技術

微服務可以用不同的程式語言實現，也可以使用不同的基礎設施。因此，最重要的技術選擇是微服務之間的通信方式（同步、異步、UI集成）以及用於通信的協議（RESTful HTTP、消息、GraphQL……）。在傳統系統中，大多數技術選擇，如程式語言，都會影響整個系統。因此，選擇技術的方法是完全不同的。

Eclipse基金會已經發布了開發微服務的規範——Eclipse MicroProfile。

### Service mesh

在服務網格中，每個服務實例都與一個反向代理伺服器實例（稱為服務代理、 sidecar代理或sidecar）配對。服務實例和 sidecar 代理共享一個容器，容器由一個容器編排工具（如Kubernetes、Nomad、Docker Swarm、DC/OS）管理。

服務代理負責與其他服務實例的通信，並支持服務（實例）發現、負載平衡、身份驗證和授權、安全通信等功能。

在服務網格中，服務實例及其sidecar代理被稱為構成數據平面，其中不僅包括數據管理，還包括請求處理和響應。服務網格還包括一個用於管理服務之間交互的控制平面，這些交互由它們的sidecar代理協調。服務網格架構有幾個選項: Istio、Linkerd、Consul和其他許多服務網格景觀。服務網格管理平面 Meshery 提供跨服務網格部署的生命周期、配置和性能管理。

### 平台比較

實現微服務體系結構非常困難。任何微服務體系結構都需要解決許多問題（見下表）。Netflix開發了一個微服務框架來支持他們的內部應用程式，然後開放了該框架的許多部分。其中許多工具已經通過Spring框架得到推廣——它們已經在Spring Cloud項目的保護傘下重新實現為基於Spring的工具。下表顯示了Kubernetes生態系統中的實現功能與Spring Cloud世界中的等效功能的比較。Spring Cloud生態系統值得注意的一點是，它們都是基於Java的技術，而Kubernetes是一個多語言運行時平台。

微服務｜Spring Cloud與Netflix OSS｜Kubernetes

配置管理：微服務應用程式的配置需要從代碼中進行外部化，並可以通過簡單的服務調用進行檢索。｜Spring Config Server、Netflix Archaius都支持基於Git存儲庫的配置位置。Archaius支持配置數據類型。｜Kubernetes ConfigMaps通過服務公開存儲在etcd中的配置。Kubernetes Secrets支持基於服務的安全部署和敏感配置資訊（例如密碼，證書等）的使用。

服務發現：維護微服務域中可用於工作的服務實例列表。｜Spring Cloud Eureka允許客戶端向其註冊，與註冊的客戶端保持心跳，並將服務名稱映射到按服務名稱查找服務的客戶端的主機名。｜Kubernetes Services提供集群內部可用的服務實例的部署時註冊。Ingress是一種機制，通過這種機制，服務可以向集群之外的客戶端公開。

負載平衡：擴展分布式系統的關鍵是能夠運行一個組件的多個實例。然後要通過負載均衡器將負載分配到這些實例上。｜Spring Cloud Ribbon為服務客戶端提供跨服務實例負載平衡的能力。｜Kubernetes Service提供了跨服務實例對服務進行負載平衡的能力。這與Ribbon提供的功能不同。

API網關：微服務提供的API的粒度通常與服務客戶端需要的粒度不同。API網關實現表層，並提供其他服務，如代理、協議轉換和其他管理功能。｜Spring Cloud Zuul提供基於配置的API表層｜Kubernetes Service和Ingress resources、Istio、Ambassador是提供南北（進出數據中心）和東西（跨數據中心或雲或地區的通信）API網關功能的解決方案。

安全問題：許多安全問題推給API網關來實現。對於分布式微服務應用程式，不重新造安全方面的輪子，允許在所有服務共享的組件中進行策略定義和實現是有意義的。｜Spring Cloud Security通過Spring Cloud Zuul解決了許多安全問題｜Kubernetes生態系統提供了像Istio這樣的服務網格，該網格能夠通過其API網關機制提供安全性。

集中化日誌記錄：擁有一個集中化的日誌收集和分析基礎設施來管理大量的服務非常重要——其中許多服務是以分布式方式運行的。｜ELK技術棧（Elasticsearch、LogStash、Kibana）｜EFK技術棧（Elasticsearch、Fluentd、Kibana）

集中的度量：一個可以監控單個服務和整個系統的健康和性能的集中區域對於正確的操作是必不可少的。｜Spring Spectator & Atlas｜Heapster, Prometheus, & Grafana

分布式跟蹤：每個進程的日誌記錄和度量監視都有其存在的地方，但它們都不能重構事務在跨分布式系統傳播時所採用的複雜路徑。分布式跟蹤是微服務平台必不可少的工具。｜Spring Cloud Sleuth｜Hawkular, Jaeger

彈性和容錯性：分布式系統必須能夠圍繞故障進行自動路由，並且能夠將請求路由到提供最佳響應的服務實例。｜Spring Hystrix, Turbine, & Ribbon｜Health check, service meshes (example: Istio)

自動伸縮和自我修復：分布式系統通過水平伸縮響應更高的負載: 平台必須檢測並自動響應這些條件。此外，系統需要檢測故障，並嘗試自動重啟，無需操作員輸入。｜健康檢查、自我修復和自動縮放

打包、部署和調度: 大規模系統需要健壯的包管理和部署系統來管理滾動部署或藍綠色部署，並在必要時進行回滾。調度程序幫助確定可以根據當前條件將一組新服務部署到哪個特定的執行節點。｜Spring Boot, Apache Maven. Spring Cloud系統沒有真正的調度程序。｜Docker, Rkt, Kubernetes Scheduler & Deployment, Helm

作業管理：控制無人值守的後台程序執行。｜Spring Batch｜Kubernetes Jobs與Scheduled Jobs

單例應用程式：限制特定服務作為該服務在整個系統中的唯一實例運行。｜Spring Cloud Cluster｜Kubernetes Pods

## 微服務採用者

- Akana
- Amazon
- AnyPresence JustAPIs
- Apprenda
- Axway
- 1060 Research Ltd.
- Bluemix
- Cloud Foundry
- Google
- The Guardian
- Hailo Taxi
- HP Helion Development Platform
- Jelastic
- Microsoft Azure
- Netflix
- Nirmata
- nearForm
- Riot Games
- SoundCloud
- Uber
- Joined Node

## 平台實作

- Apache ServiceComb
- Docker
- Microsoft Service Fabric ( overview , blog announcement )
- MicroService4Net
- NetKernel
- Nirmata
- Seneca Microservices Framework and Protocol
- Spring Cloud
- 微服務測試工具：Wilma
- Vert.x
- Baratine
- KumuluzEE
- Enduro/X