1 系統設計
1.1 總體框架
1.1.1 功能架構
微服務平臺主要由服務支撐層、基礎服務層、通用服務及業務服務層組成,系統總體功能架構圖如下:
1) 基礎設施
微服務平臺的基礎設施包括網絡、存儲、計算等硬件基礎設施,為平臺的運行提供基礎保障。
2) 服務支撐層
服務支撐層為保證整個服務平臺健康、高效運行提供支撐服務,包括服務注冊與發現中心、配置中心、日志中心、監控中心、服務限流降級與熔斷、微服務網關等支撐服務功能。
3) 基礎服務層
基礎服務層將平臺通用的功能以服務的形式進行封裝,為其他業務服務的實施提供基礎服務,包括分布式緩存服務、分布式存儲服務、搜索服務、消息隊列服務、分布式事務服務、任務調度服務、統一認證中心、用戶中心、組織機構管理、代辦任務中心、流程管理中心等基礎服務功能。
4) 通用服務層
通用服務層,是將一般業務功能開發都需要使用的功能進行封裝,形成通用服務,提高開發效率,控制開發質量的一種方式。
5) 業務服務層
通過通用服務實現的業務邏輯部署在業務服務層,為前端應用提供服務。
1.1.2 邏輯架構
平臺架構以Spring Cloud 微服務架構為核心進行構建,集成了Spring Cloud Alibaba Nacos 實現服務注冊、發現與配置管理,集成Skywalking、 Elastic Logstash、Elastic Search、Elastic Kibana 實現日志中心功能、集成Prometheus、Grafana 實現監控預警功能、集成Spring Cloud Admin 實現微服務監控功能、集成Alibaba Sentiel 實現服務限流、降級與熔斷功能,集成Spring Cloud Gateway 實現了微服務網關功能。
1.2 詳細功能說明
1.2.1 服務支撐層
服務支撐層為保證整個服務平臺健康、高效運行提供支撐服務,包括服務注冊與發現中心、配置中心、日志中心、監控中心、服務限流降級與熔斷、微服務網關等支撐服務功能。
1.2.1.1 服務注冊、發現與配置
Spring Cloud Alibaba Nacos 是阿里巴巴公司的開源組件,Nacos 提供了一組簡單易用的特性集,能夠快速實現動態服務注冊、發現、服務配置、服務元數據及流量管理功能,幫助企業更敏捷和容易地構建、交付和管理微服務平臺,是構建以“服務”為中心的現代應用架構服務的基礎設施。
- 服務發現和服務健康監測
Nacos支持基于DNS和基于RPC的服務發現。服務提供者使用原生SDK、OpenAPI或一個獨立的Agent TODO注冊服務后,服務消費者可以使用DNS TODO 或HTTP&API查找和發現服務。
Nacos提供對服務的實時的健康檢查,阻止向不健康的主機或服務實例發送請求。Nacos支持傳輸層 (PING或TCP)和應用層 (如 HTTP、MySQL、用戶自定義)的健康檢查。對于復雜的云環境和網絡拓撲環境中(如 VPC、邊緣網絡等)服務的健康檢查,Nacos提供了Agent上報模式和服務端主動檢測2種健康檢查模式。Nacos 還提供了統一的健康檢查儀表盤,幫助根據健康狀態管理服務的可用性及流量。
- 動態配置服務
動態配置服務可以平臺以中心化、外部化和動態化的方式管理所有環境的應用配置和服務配置。
動態配置消除了配置變更時重新部署應用和服務的需要,讓配置管理變得更加高效和敏捷。
配置中心化管理讓實現無狀態服務變得更簡單,讓服務按需彈性擴展變得更容易。
- 動態 DNS 服務
動態 DNS 服務支持權重路由,讓平臺更容易地實現中間層負載均衡、更靈活的路由策略、流量控制以及數據中心內網的簡單DNS解析服務。動態DNS服務使平臺更容易地實現以 DNS 協議為基礎的服務發現,以幫助消除耦合到第三方應用私有服務發現API上的風險。
1.2.1.2 服務監控中心
整個平臺分布著大量的服務器、中間件、數據庫、微服務組件,對他們的性能、運行指標、健康狀況的監控就顯得尤為重要。方案通過多種組件集成的方式提供了整個平臺的可視化監控中心功能。
- 分布式鏈路追蹤
隨著業務的發展,平臺中提供的服務會越來越多,服務之間的調用也會越來越錯綜復雜,一個請求可能會涉及多個服務,而服務本身可能也會依賴其他服務,整個請求路徑就構成了一個網狀的調用鏈,而在整個調用鏈中一旦某個節點發生異常,整個調用鏈的穩定性就會受到影響,為此方案中通過集成Apache SkyWalking組件,來幫助我們快速定位和解決問題。
Apache SkyWalking包括了分布式追蹤、性能指標分析、應用和服務依賴分析功能。SkyWalking 核心包括探針Probo、后臺服務Backend、存儲Storage、可視化UI 四部分組件,其中存儲我們選用Elastic Search 企業級搜索服務來來存儲監控日志信息。
SkyWalking 的探針只需要部署到要監測服務的服務器上,即可實現代碼無侵入的方式收集服務相關日志信息。
探針收集到數據并進行格式轉換后,將數據推送到后臺服務,后臺服務對收集的數據進行分析和聚和后存儲到本方案選取的存儲Elastic Search 上,以便可視化展示給最終用戶。
- 服務器與組件監控
為了及時了解平臺的健康情況,我們需要建包括服務器的CPU空閑率、CPU 使用率、CPU負載率、可用內存、內存使用率、文件系統空閑空間、網絡上傳、下載速率、磁盤IO情況,數據庫吞吐量、連接情況、緩沖池使用情況、查詢性能,Elastic Search 的查詢索引性能、內存分配、垃圾回收情況、集群健康及節點可用性等多種指標。為此,本方案采用Prometheus組件實現平臺的監控與報警功能。Prometheus 是一套開源的系統監控報警框架,他包含了多個獨立的組件,其中有些組件是可選的,我們方案主要選擇如下組件:
- Prometheus Server: 用于收集和存儲時間序列數據;
- Exporters: 用于暴露已有的第三方服務metrics給Prometheus,本方案中主要用到了Node-Exporter、Oracle Exporter、 Mysqld-Exporter、ElasticSearch-Exporter、redis-Exporter;
- Alertmanager: 從Prometheus server 端接收到報警后,會進行去除重復數據級分組操作,并通過郵件、短信等方式發出報警;
主要工作流程:
- Prometheus serve定期從配置好的exporters中拉取metrics;
- Prometheus server 在本地存儲收集到的 metrics,并運行已定義好的 alert.rules,記錄新的時間序列或者向Alertmanager推送報警信息;
- Alertmanager根據配置文件,對接收到的警報進行處理,發出告警;
- 在圖形界面中,可視化顯示采集數據;
1.2.1.3 日志中心
在各個微服務開發實現過程中,根據業務需要我們會設置一些埋點記錄應用日志,比如用Log4j記錄應用日志信息,以便我們對應用進行分析排查問題或做統計分析。為了能夠實時、可視化的方式對日志進行統計、分析、查看,方案選用ELK開源組件實現日志中心功能。ELK核心組件包括:
- Elasticsearch:分布式搜索和分析引擎,具有高可伸縮、高可靠和易管理等特點。能對大容量的數據進行接近實時的存儲、搜索和分析操作;
- Logstash:數據收集引擎。它支持動態的從各種數據源搜集數據,并對數據進行過濾、分析、豐富、統一格式等操作,然后存儲到用戶指定的位置;
- Kibana:數據分析和可視化平臺。通常與Elasticsearch配合使用,對其中數據進行搜索、分析和以統計圖表的方式展示;
- Filebeat:一個輕量級開源日志文件數據搜集器。在需要采集日志數據的服務上安裝Filebeat,并指定日志目錄或日志文件后,Filebeat 就能讀取數據,實時發送到Logstash進行解析,也可以直接發送到Elasticsearch進行集中式存儲和分析。
另外,我們經常遇到一些需要將數據庫中的數據同步到Elasticsearch中,以便提高查詢效率、降低數據庫服務器壓力的情況,為了實現這樣的功能通常有幾個方案:
- 代碼實現(雙寫),針對代碼中進行數據庫的增刪改操作時,同時進行elasticsearch的增刪改操作;
- mybatis實現,通過mybatis plugin截取sql語句進行分析, 針對insert、update、delete的語句進行處理;
- AOP實現,根據制定的規則,如規范方法名,注解等進行切面處理;
- Logstash,利用Logstash支持動態的從各種數據源搜集數據的特性,可以進行數據的同步,只需要簡單的配置就能將Mysql、Oracle等數據庫的數據同步到Elasticsearch,但是Logstash的原理是每分鐘進行一次增量數據查詢,將結果同步到Elasticsearch,如果實時性要求不是特別高的情況建議使用此方案;另外,如果是只針對Mysql數據庫的情況,可以利用阿里巴巴的Canal組件與Logstash相結合的方式實現實時數據同步到Elasticsearch。
1.2.1.4 服務限流、熔斷降級
隨著平臺中微服務組件的不斷增加,如何在其中一個或幾個服務出現流量異常的情況下,保障其他服務能夠正常運轉,而不至于整個平臺陷入癱瘓顯得越來越重要。
阿里巴巴Sentinel 是面向微服務架構的輕量級流量控制組件,主要以流量為切入點,從限流、流量整形、熔斷降級、系統負載保護等多個維度來幫助您保障微服務的穩定性。
- 流量控制,流量控制在網絡傳輸中是一個常用的概念,它用于調整網絡包的發送數據。然而,從系統穩定性角度考慮,在處理請求的速度上,也有非常多的講究。任意時間到來的請求往往是隨機不可控的,而系統的處理能力是有限的。因此需要根據系統的處理能力對流量進行控制。Sentinel讓我們從 控制資源的調用關系(例如資源的調用鏈路,資源和資源之間的關系)、運行指標(例如 QPS、線程池、系統負載等)、控制的效果(例如直接限流、冷啟動、排隊)等角度,進行靈活組合,從而達到想要的效果。
- 熔斷降級,除了流量控制以外,及時對調用鏈路中的不穩定因素進行熔斷也是 Sentinel 的使命之一。由于調用關系的復雜性,如果調用鏈路中的某個資源出現了不穩定,可能會導致請求發生堆積,進而導致級聯錯誤。因此當檢測到調用鏈路中某個資源出現不穩定的表現(例如請求響應時間長或異常比例升高)的時候,則對這個資源的調用進行限制,讓請求快速失敗,避免影響到其它的資源而導致級聯故障。
- 系統負載保護,Sentinel同時提供系統維度的自適應保護能力。防止雪崩,是系統防護中重要的一環。當系統負載較高的時候,如果還持續讓請求進入,可能會導致系統崩潰,無法響應。在集群環境下,網絡負載均衡會把本應這臺機器承載的流量轉發到其它的機器上去。如果這個時候其它的機器也處在一個邊緣狀態,這個增加的流量就會導致這臺機器也崩潰,最后導致整個集群不可用。針對這個情況,Sentinel 提供了對應的保護機制,讓系統的入口流量和系統的負載達到一個平衡,保證系統在能力范圍之內處理最多的請求。
1.2.1.5 微服務網關
平臺中部署了很多微服務,這些微服務對外提供API接口以便客戶端調用,每個微服務都有各自的地址、端口等信息,一個客戶端可能需要訪問很多不同的微服務去實現業務功能。這就需要客戶端動態維護微服務的信息并與多個微服務之間進行身份驗證工作,為了解決這些問題,就需要一個能夠統一管理API 的網絡關口,作為整個微服務平臺請求的唯一入口,在網關層處理所有非業務功能(比如對調用微服務的客戶端進行身份驗證、記錄日志、動態路由等),本方案采用Spring 官方推出的 Spring Cloud Gateway 網關組件,具有如下特性:
- 是基于Spring Framework 5和 Spring Boot 2.x 的響應式、非阻塞式的 API;
- 動態路由:能夠匹配任何請求屬性;
- 可以對路由指定 Predicate(斷言)和 Filter(過濾器);
- 集成Hystrix的斷路器功能;
- 集成 Spring Cloud 服務發現功能;
- 易于編寫的 Predicate(斷言)和 Filter(過濾器);
- 請求限流功能;
- 支持路徑重寫。
客戶端向Spring Cloud Gateway發出請求。如果Gateway Handler MApping確定請求與路由匹配,則將其發送到Gateway Web Handler。此handler通過特定于該請求的過濾器鏈處理請求。而這些匹配是由路由斷言Factory完成的,Spring Cloud Gataway包含了很多內置的路由斷言Factories,這些斷言都匹配HTTP請求的不同屬性。多個路由斷言Factories可以通過 and 進行組合使用。
主要內置斷言Factory包括:
- After 路由斷言Factory,After Route Predicate Factory采用一個參數—日期時間。在該日期時間之后發生的請求都將被匹配;
- Before 路由斷言Factory,Before Route Predicate Factory采用一個參數—日期時間。在該日期時間之前發生的請求都將被匹配;
- Between 路由斷言 Factory,Between 路由斷言 Factory有兩個參數,datetime1和datetime2。在datetime1和datetime2之間的請求將被匹配。datetime2參數的實際時間必須在datetime1之后;
- Cookie 路由斷言Factory, Cookie 路由斷言 Factory有兩個參數,cookie名稱和正則表達式。請求包含次cookie名稱且正則表達式為真的將會被匹配;
- Header 路由斷言Factory,Header 路由斷言 Factory有兩個參數,header名稱和正則表達式。請求包含次header名稱且正則表達式為真的將會被匹配;
- Host 路由斷言Factory, Host 路由斷言 Factory包括一個參數:host name列表。使用Ant路徑匹配規則,.作為分隔符;
- Method 路由斷言 Factory,Method 路由斷言 Factory只包含一個參數: 需要匹配的HTTP請求方式;
- Path 路由斷言 Factory,Path 路由斷言 Factory 有2個參數: 一個Spring PathMatcher表達式列表和可選;
- Query 路由斷言 Factory,Query 路由斷言 Factory 有2個參數: 必選項 param 和可選項 regexp;
- RemoteAddr 路由斷言 Factory,RemoteAddr 路由斷言 Factory的參數為 一個CIDR符號(IPv4或IPv6)字符串的列表,最小值為1,例如192.168.0.1/16(其中192.168.0.1是IP地址并且16是子網掩碼)
另外,Spring Cloud Gateway 可以與Oauth2、JWT集成實現在網關進行請求的身份驗證與授權功能。
1.2.2 基礎服務層
基礎服務層將平臺通用的功能以服務的形式進行封裝,為其他業務服務的實施提供基礎服務,包括分布式緩存服務、分布式存儲服務、搜索服務、消息隊列服務、分布式事務服務、任務調度服務等基礎服務功能
1.2.2.1 分布式緩存服務
分布式緩存服務可將高頻訪問的數據,放入緩存中,可以大大提高微服務平臺整體的承載能力,解決數據庫服務器和web服務器之間的效率瓶頸。分布式緩存服務應支持高性能的Key-Value存儲方式,支持string、list、hash、set、zset、hypeloglog等多種數據結構,支持主動過期和惰性過期的數據過期處理,支持volatile-lru、volatile-ttl等LRU策略,及內存管理、內容存儲+磁盤持久化、主從復制等功能;在性能上應滿足百萬級QPS的資源調用,99.99%的可用性,毫秒級的核心請求響應時間,彈性擴展、易用等指標。
方案采用Redis來提供分布式緩存服務,可以完全滿足上述要求:
Redis,是REmote DIctionary Server的縮寫。是一個開源、基于C語言、基于內存亦可持久化的高性能NoSQL數據庫,同時,它還提供了多種語言的API。它是一款由意大利人由Salvatore Sanfilippo所寫的,依據BSD開源協議發行的高性能Key-Value存儲系統(cache and store)。它通常被稱為數據結構服務器,提供了一些豐富的數據結構,包括 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等類型。Redis當然還包括了對這些數據結構的豐富操作。
1.2.2.2 分布式存儲服務
分布式網絡存儲服務采用可擴展的系統結構,利用多臺存儲服務器分擔存儲負荷,利用位置服務器定位存儲信息,它不但提高了系統的可靠性、可用性和存取效率,還易于擴展。分布式存儲服務應支持文件存儲、文件傳輸、跨機房架構、文件元數據管理、文件搜索、文件處理、文件版本管理、文件日志消息、大數據對接等功能,對外提供RESTfulAPI。
針對以上的需求我們采用MongoDB來應對。
MongoDB是一個基于分布式文件存儲的數據庫。由C++語言編寫。旨在為WEB應用提供可擴展的高性能數據存儲解決方案。是介于關系數據庫和非關系數據庫之間的產品,是非關系數據庫當中功能最豐富,最像關系數據庫的。他支持的數據結構非常松散,是類似json的bson格式,因此可以存儲比較復雜的數據類型。Mongo最大的特點是他支持的查詢語言非常強大,其語法有點類似于面向對象的查詢語言,幾乎可以實現類似關系數據庫單表查詢的絕大部分功能,而且還支持對數據建立索引。
1.2.2.3 消息隊列服務
消息隊列服務可以為平臺提供消息發布訂閱、消息軌跡查詢、定時(延時)消息、資源統計、監控報警等一系列消息服務,為平臺提供異步解耦、削峰填谷的能力,同時具備海量消息堆積、高吞吐、可靠重試等互聯網應用所需的特性。
我們采用Apache Alibaba RocketMQ做為消息隊列服務實現方案,Apache Alibaba RocketMQ 是一款分布式、隊列模型的消息中間件,具有以下特點:
- 支持嚴格的消息順序
- 支持 Topic 與 Queue 兩種模式
- 億級消息堆積能力
- 比較友好的分布式特性
- 同時支持 Push 與 Pull 方式消費消息
- 歷經多次天貓雙十一海量消息考驗
對比其他主流消息隊列組件主要優勢有:
- 支持事務型消息(消息發送和 DB 操作保持兩方的最終一致性,RabbitMQ 和 Kafka 不支持)
- 支持結合 RocketMQ 的多個系統之間數據最終一致性(多方事務,二方事務是前提)
- 支持 18 個級別的延遲消息(RabbitMQ 和 Kafka 不支持)
- 支持指定次數和時間間隔的失敗消息重發(Kafka 不支持,RabbitMQ 需要手動確認)
- 支持 Consumer 端 Tag 過濾,減少不必要的網絡傳輸(RabbitMQ 和 Kafka 不支持)
- 支持重復消費(RabbitMQ 不支持,Kafka 支持)
1.2.2.8 搜索引擎服務
通過搜索引擎服務將搜索引擎復雜的索引結構概念簡單化、可視化和自助定制化。平臺的上層業務應用可以通過控制臺創建搜索應用,定制文檔字段的結構和屬性,包括字段名稱、類型、分詞方式、搜索屬性等。搜索應用在運行過程中可以自由修改,滿足業務快速變化的需求,縮短需求變更到上線的過程。
本方案中,我們基于Elastic Search實現搜索引擎服務,Elasticsearch 是一個實時的分布式搜索和分析引擎。它可以幫助用戶用前所未有的速度去處理大規模數據、它可以用于全文搜索,結構化搜索以及分析。實現分布式實時文件存儲,并將每一個字段都編入索引,使其可以被搜索,他是一個能夠實現實時分析的分布式搜索引擎,并可以擴展到上百臺服務器,處理PB級別的結構化或非結構化數據。
1.2.2.9 分布式事務
在微服務架構下,雖然我們會盡量避免分布式事務,但是只要業務復雜的情況下這是一個繞不開的問題,為了保證業務數據原子性、一致性,本方案采用阿里巴巴開源的一站式分布式事務解決方案中間件Seata, Seata能夠幫助用戶以高效并且對業務 零侵入的方式解決微服務場景下面臨的分布式事務問題。
Seata整體事務邏輯是基于兩階段提交 的模型,核心概念包括以下3個角色:
- TM:事務的發起者。用來告訴TC,全局事務的開始,提交,回滾。
- RM:具體的事務資源,每一個 RM 都會作為一個分支事務注冊在TC。
- TC:事務的協調者Seata-Server,用于接收我們的事務的注冊,提交和回滾。
Seata有兩種模式可使用分別對應不同業務場景:
- AT模式, 該模式適合的場景:
基于支持本地 ACID 事務的關系型數據庫。
JAVA 應用,通過 JDBC 訪問數據庫。
- 一個典型的分布式事務過程:
① TM 向 TC 申請開啟一個全局事務,全局事務創建成功并生成一個全局唯一的 XID。
② XID 在微服務調用鏈路的上下文中傳播。
③ RM 向 TC 注冊分支事務,將其納入 XID 對應全局事務的管轄。
④ TM 向 TC 發起針對 XID 的全局提交或回滾決議。
⑤ TC 調度 XID 下管轄的全部分支事務完成提交或回滾請求。
- MT模式, 該模式邏輯類似TCC,需要 自定義實現prepare、commit和rollback的邏輯,適合 非關系型數據庫 的場景