什麼是微服務
微服務其實說的是一種架構,是一種由多個微型服務組成的一種架構方式,其中對這些微型服務的要求是:
- 高度可維護和可測試;
- 松耦合;
- 獨立部署;
- 根據業務組織調整;
- 是由專門的團隊負責;
如下圖所示:
與傳統的單體架構(Monolithic Architecture)的對比
傳統服務部署的特點:
把所有的功能和模塊集中到一個應用中,然後將其按照war的方式部署在servlet容器中(比如tomcat),提供了所有對外的接口和功能;
優點:
- 易開發(當前的工具都是爲了開發單個應用而設計,方便開發人員開發和測試);
- 易部署(只要將程序打包成爲war,部署到容器中即可);
- 易擴展(只要多啓動幾個容器實例即可);
但是上面說的有點僅限於應用程序體量小時存在,當應用的體量大幅度提升後上面的優點就變成了缺點:
- 難開發:
- 當體量變大後,開發人員需要熟悉所有的業務邏輯,尤其對新人而言;
- 當前的開發工具會隨着應用變大而變慢,影響開發效率;
- 難部署:
- 容器的啓動時間會隨其應用的體量增大而增大;
- 持續交付和部署會很難,因爲頻繁的部署大應用可能會中斷其中的任務,比如使用了Quartz job等;
- 難擴展:
- 所有的擴展實例都是需要訪問所有的資源(IO/DB)等,不能根據數據量來進行調整,比如有的模塊是消耗CPU的,有的模式是消耗內存的;
- 不能很好的形成自己專門的技術棧,所有人需要學習所有的邏輯,而不是每個模塊有專人負責;
- 不能很好的進行技術的更新;
微服務的優點:
- 方便持續交付和持續部署;
- 改善可維護性-小型服務都容易理解和修改;
- 每個微服務可以獨立部署;
- 團隊之間更獨立;
- 每個微服務都相對較小:
- 易於開發人員理解和開發;
- 開發工具更快更高效;
- 服務啓動更快,更快部署;
- 改善故障隔離-如果其中一個微服務故障,其他微服務仍可繼續提供服務;
- 方便更新技術棧-可以保證最小影響來使用更新的技術棧或版本;
微服務的缺點:
與傳統一樣,在不同的情形下優點也是缺點,如果在小體量的團隊和應用面前,微服務的優點就是缺點了:
- 不方便開發
- 聯調時需要本地啓動多個應用;
- 需要實現服務間的通信及處理部分異常情形;
- 增大測試成本;
- 不方便部署(小體量改版往往是整體模塊都受影響,所以需要部署多個服務);
- 資源浪費(有的小模塊對資源需求很小,但如果以服務方式啓動就會浪費);
使用微服務會涉及到模式
下面的圖是使用微服務開發可能會涉及到模式:
如果要使用微服務架構,那麼會涉及到很多問題,爲了解決這些問題及連鎖問題,就出現了與問題對應的解決模式,一共可以分爲14類。下面的模式其實是一些通用的模式:
- 應用架構-Application architecture patterns:
- Monolithic architecture - 單體架構;
- Microservice architecture - 微服務架構;
這個解決模式是總體的,下面的解決模式是基於應用架構選擇了微服務架構的前提下;
- Decomposition - 分解
- decompose by business capability - 按業務能力分解 - 可以理解爲按照公司部門進行拆分-康威定理;
- decompose by subdomain - 按子域分解 - 可以理解爲按照領域(或者說按照信息處理流程)進行拆分;
遵循的原理:參考面向對象設計(OOD)中的單一職責原則(Single Responsibility Principle-SRP)和公共閉合原則(Common Closure Design-CCP)進行拆分;
- Data management - 數據管理
- Database per Service - 數據庫服務隔離-dps;
如果服務之間採用各自獨立數據庫,那麼會有數據一致性的問題;爲了解決服務間的事物問題和多表聯查的查詢問題,分別引入了:- Saga模式 - 通過分解爲多個本地事物來解決服務間的數據一致性,
實現方式有兩種方式:- 編制(Orchestration-管絃樂)-通過引入一箇中心控制者來協調工作;
- 編排(Choreography-舞蹈術)-通過定義一些列通用規則達到相互之間的協同工作;
- API Composition-通過將不同服務的數據查詢彙總到內存後,在內存中進行join來解決;
- Command Query Responsibility Segregation (CQRS)- 通過定義一個只讀的視圖數據庫來實現多表聯查,視圖數據庫中的數據通過
訂閱目標數據所屬服務的Domain Event-域事件來實現數據的更新,
而域事件是通過將業務邏輯封裝爲一系列的DDD(Domain Driven Design)集合,當業務邏輯發生新增或者修改等變動時通過發佈domain events
來告知其他訂閱的服務;而Event sourcing事件收集通過將事件
序列化存儲(類似於mq)來達到可以發佈一致性的消息的目的。
- Saga模式 - 通過分解爲多個本地事物來解決服務間的數據一致性,
- Shared database(共享數據庫)sd;
- Database per Service - 數據庫服務隔離-dps;
- Transactional messaging - 事務性消息
- Transactional outbox - 事務性發件箱 -
通過在關係型數據庫中新建一張outbox表來實現,將outbox表中數據插入更新的操作放在本地的事物中即可; - Transaction log tail - 事物更新日誌 -
與事務性消息類似,另建一張表,只不過表中存儲的是數據庫的最新的事務日誌,再另起一個線程將更新後的數據發送給消息中繼(Message Relay),
最後發送給消息代理(Message Broker)。 - Polling publisher- 與outbox的區別?
- Transactional outbox - 事務性發件箱 -
- Communication Style - 通信模式
- RPI - 遠程過程調用 - 常用的方式有:
- REST: 最常見的就是http服務
- RPC:gRPC
- Apache Thrift
- Messaging - 消息,比如kafka、rocketMQ等;
- Domain-Specific Protocol - 特定領域協議 - 比如郵件協議SMTP和IMAP;
- RPI - 遠程過程調用 - 常用的方式有:
- Reliability - 可靠性
- Circuit Break - 熔斷 -
爲了防止服務不可用導致雪崩效應而設立的一種保護機制,主要是通過代理調用的服務,統計調用服務的情況,如果失敗率達到一定閾值,則開啓熔斷一定時間,
熔斷時間過後會開啓半開(half-open)狀態,半開狀態下如果調用的服務正常則關閉熔斷,否則轉爲全熔斷狀態一定時間;
- Circuit Break - 熔斷 -
- Service discovery - 服務發現
- Client-side discovery - 客戶端側 -
由調用方直接調用Service Registry獲取服務方的地址; - Server-side discovery - 服務端側 -
調用方調用一個路由,路由再調用Service Registry服務獲取地址 - Service registry - 註冊服務 -
其實就是一個數據庫,庫中維護各個服務可用的地址,但Service Registry本身的地址是固定的。服務註冊又可以分爲以下兩種:- Self registration - 自注冊 -
服務啓動時自己向註冊服務註冊,服務關閉時自己向註冊服務解註冊;- An AWS Elastic Load Balancer (ELB);
- Aliyun Service Load Balancer (SLB);
- 3rd party registration - 第三方註冊 -
依賴第三方註冊商,當服務啓動時,註冊商向註冊服務註冊,當服務關閉時,註冊商向註冊服務解註冊。- Netflix Prana - a “side car” application that runs along side a non-JVM application and registers the application with Eureka.
- AWS Autoscaling Groups automatically (un)registers EC2 instances with Elastic Load Balancer
- Joyent’s Container buddy runs in a Docker container as the parent process for the service and registers it with the registry
- Registrator - registers and unregisters Docker containers with various service registries
- Clustering frameworks such as Kubernetes and Marathon (un)register service instances with the built-in/implicit registry
- Self registration - 自注冊 -
- Client-side discovery - 客戶端側 -