一、前言
為了實現基于微服務開發的產品,或者說為了將單體應用重構為微服務架構時,將面臨著眾多技術框架的選擇。大公司往往會有專門的部門或團隊來負責自主研發自己的框架,以滿足產品的需要,但是對于一般的中小型企業,選擇合適的開源框架就顯得更接地氣了。本章將簡單介紹微服務中,在技術選型時需要注意哪些原則,一些常用的開源技術框架,希望能夠為大家在進行技術選型、調研時提供一些思路方向。
筆者面試過很多程序員,一提及微服務,就會具體說到Spring Boot、Spring Cloud,然后就是“背誦”各種具體的用法和配置文件。并不是說這樣不對,但我們更希望知道的是這些技術框架的原理,為什么選擇它,它與其他類似框架又有何不同呢。
至于一個技術框架該怎么用,它適用于什么場景,筆者建議可以直接閱讀官方或對應的github上的文檔,有需要時還可以閱讀下關注點的源碼,這樣對正確的理解它,是很有必要的,畢竟官方發布的東西是相對權威的,其他地方的資料或許存在片面性,對大家的使用、理解存在一定的誤導。(這只是筆者對大家在技術選型時,查閱資料的一些建議)
二、選型原則
在軟件開發領域,幾乎每天都有新的技術框架誕生、更新,一些新的概念更是層出不窮,技術選型時,難免讓人無從抉擇。對于技術選型,我個人有以下幾點建議:
1.有需求,再引入
在微服務架構中,各類組件/技術很多很多,但并不意味著所有的都應該引入你的項目,倘若單純為了覆蓋全技術棧或組件而全部引入,這將是一種很不明智的選擇。后續將會成為你項目的累贅,讓你苦不堪言。
只要你記住這六個字:“有需求,再引入”,就OK了。伴隨著項目體系架構的完善、功能的健全,當有某方面的需求時,在逐步考慮是否引入某些技術組件。
2.選擇最熟悉、使用最多的技術
“一個新項目里最好不要使用超過30%的新技術”,我覺得這句話是有一定道理的。對于你完全不知道、不了解的技術,你是無法預估、掌控在使用過程中會出現的任何風險,一旦出現問題,短時間內解決不了,你將會變得很難堪。
在這里不是說拒絕使用、接觸新技術,新技術是值得大家去追捧、了解、學習,一些新技術在很大程度上能給我們帶來前所未有的利處,解決其他技術框架解決不了的問題。這里所說的“新技術”,是指沒有經過充分的考察、技術驗證、存在種種疑惑的技術,而是一味的拿來主義,這樣的風險可想而知。
確保選擇的技術,是業界使用最多的、被大家認可的技術,即使出現了問題,也能應對自如。至少在團隊內部小范圍是非常認可的。
3.強大社區支撐的技術
GitHub上star的數量是一個重要指標,同時參考近年來代碼、文檔、issues等更新頻率,各大技術博客是否有相關技術分享記載,這些都是能夠說明該技術是否活躍、受歡迎程度、使用人群多少等。
擁有強大社區支持的技術,在選型后,倘若使用出現疑問、問題、bug等,能夠有地方可提、可修復、可深究探討,畢竟現在的技術社區都是足夠開放的。
慎選個人開源的技術框架、組件等,里面到底有多少坑,沒幾個人能說清楚的,況且說不定哪天就不復存在了呢。
4.從業務、項目規模出發
任何技術的出發點都是為最終業務而服務的,不同業務、不同項目規模,對技術的要求指標都是不同的。處于初創期的業務,選型的基準是相對靈活,畢竟業務相對簡單,支撐業務不是很大,只要夠用、開發效率足夠高就好。處于復雜業務而重構的項目,選型就需謹慎,往往伴隨著一些復雜需求誕生、規模大小的不確定性,不得不考慮選型技術可能伴隨著一些小修小補或者螺旋式上升的重構,則需選型便于適配、切換、替換,耦合度低的技術。
正因為技術選型和業務相關,我們能夠觀察到一些很明顯的現象:新技術往往被早期創業團隊或大公司的新興業務使用;中大型公司的核心業務則更傾向于用一些穩定了幾年的技術;一個公司如果長期使用一種技術,就會傾向于一直使用下去,甚至連版本都不更新的使用下去。
學會從業務端思考。首先我們需要充分地理解業務,理解用戶需求,理解當下需要解決的首要問題,以及可能的風險有哪些,再將目標進行分解,進行具體的技術選型、模型設計、架構設計。
5.先驗證后使用
對于未經驗證的新技術、新理念的引入一定要慎重,一定要在全方位的驗證過后,再大規模的使用,最終確定選型。新技術、新理念的出現,自然有它的誘惑,慎重并不代表保守,技術總是在不斷前進,擁抱變化本身沒有問題,但是引入不成熟的技術看似能帶來短期的收益,但是它的風險或者是后期的成本可能遠遠大于收益。驗證后,才有說服力,用著更放心。
三、技術選型
每種技術架構都有其優缺點,存在即合理,不同的業務場景使用不同的應用架構,技術框架,不一定說最新的架構、技術就是最適合你的。
微服務架構中常提及到的主要技術框架選型如下表所示,本文后面將基于此展開說明對比。
四、服務治理
1.Dubbo
Dubbo是一款高性能、輕量級的開源JAVA RPC框架,以及SOA服務治理方案。簡單的說,Dubbo就是個服務框架,說白了就是個遠程服務調用的分布式框架。它提供了三大核心能力:面向接口的遠程方法調用、智能容錯和負載均衡、以及服務自動注冊和發現,很容易和Spring框架無縫集成。
Dubbo邏輯架構如下圖所示:
- Provider:暴露服務的提供方,可以通過jar或者容器的方式啟動服務。
- Consumer:調用遠程服務的服務消費方。
- Registry:服務注冊中心和發現中心。
- Monitor:統計服務和調用次數,調用時間監控中心。(dubbo的控制臺頁面中可以顯示,目前只有一個簡單版本)
- Container:服務運行的容器。
Dubbo特點:
- 遠程通訊:提供對多種基于長連接的NIO框架抽象封裝(非阻塞I/O的通信方式,Mina/Netty/Grizzly),包括多種線程模型,序列化(Hessian2/ProtoBuf),以及“請求-響應”模式的信息交換方式。
- 集群容錯:提供基于接口方法的透明遠程過程調用(RPC),包括多協議支持(自定義RPC協議),以及軟負載均衡(Random/RoundRobin),失敗容錯(Failover/Failback),地址路由,動態配置等集群支持。
- 自動發現:基于注冊中心目錄服務,使服務消費方能動態的查找服務提供方,使地址透明,使服務提供方可以平滑增加或減少機器。
在現有的微服務架構下,Dubbo只能說是一個服務治理框架,或者說是一個RPC框架,是以接口為粒度,一個接口類就就是一個服務。如果直接用Dubbo來實現微服務架構,還缺少以下幾個功能:
- 分布式配置:可以使用Spring Cloud Config、Apollo等來實現。
- 鏈路追蹤:可以使用Zipkin、CAT等來實現。
- 批量任務:可以使用當當網開源的Elastic-Job來實現。
2.Spring Cloud
Spring Cloud是目前最主流的微服務架構落地首選方案之一,是基于Spring Boot實現的開源框架,是一個全家桶,是微服務的整體技術棧。
Spring Boot是Spring 的一套快速配置腳手架,使用默認大于配置的理念,用于快速開發單個微服務。
它為服務注冊發現、動態路由、負載均衡、配置管理、消息總線、熔斷器、分布式鏈路追蹤、大數據操作等提供了簡單的實現,讓我們可以更簡潔的使用它。
正如我們前面說過的,微服務是可以獨立部署、水平擴展、獨立訪問的服務單元,而Spring Cloud就是這些微服務的“大管家”,采用了微服務這種架構之后,項目的數量會非常多,調用鏈路復雜,從而管理成了很大的問題,而Spring Cloud框架恰恰提供了各種組件用于管理和治理微服務。理所應當的,就成了大家首選框架了。
Spring Cloud的整體架構如下圖所示,提供一站式的微服務架構解決方案。
使用Spring Cloud來構建微服務架構可以省去你整合各家技術的成本,Spring Cloud為我們構建微服務架構提供了一站式的解決方案,就好比當初Spring誕生是為解決EJB企業應用開發的眾多問題而提供的一站式輕量級企業應用開發解決方案一樣,隨著使用Spring Cloud的產品數量增加,Spring Cloud在微服務架構中已一統江湖。
下面是Spring Cloud的完整技術棧,看完你就知道它為啥會在微服務架構中一統江湖了。
3.對比、總結
通過上表對比,很容易發現Spring Cloud擁有很多的項目模塊,包含了微服務系統的方方面面。Dubbo是一個非常優秀的服務治理和服務調用框架,但缺少很多功能模塊,例如網關、鏈路追蹤等。在項目模塊上,Spring Cloud占據著更大的優勢。對比并不是否定誰,推崇誰,只是說明在不同場景下,有利優劣,需客觀來看。
如果僅關注于服務治理的這個層面,Dubbo其實還優于Spring Cloud很多:
- 支持多種序列化協議,如Hessian、HTTP、WebService。
- Dobbo Admin后臺管理功能強大,提供了路由規則、動態配置、訪問控制、權重調節、均衡負載等功能。
- 在國內影響力比較大,中文社區文檔較為全面。
- 阿里最近重啟維護,成為Apache孵化項目。
- Dubbo使用RPC協議效率更高,在極端壓力測試下,Dubbo的效率會高于Spring Cloud效率一倍多。
如果對效率有極高的要求建議使用Dubbo,相對比RPC的效率會比Restful高很多,如果選擇微服務架構去重構整個技術體系,那么 Spring Cloud是當仁不讓之選,它可以說是目前最好的微服務框架沒有之一,并且可以斷言,將來Dubbo可以很好的整合到Spring Cloud中。
五、API網關
API網關作為微服務中所有服務的唯一入口,免得業界各類成熟的技術框架組件,在進行技術選型時,需要特別考慮是否擁有以下特性:
- 高可用:網關是對外的唯一關口,必須保證 7 * 24小時可用,持續提供穩定可靠的服務。
- 高性能:所有的請求都會經過網關,它承受的壓力是巨大的,所以必須保證它具備良好的性能,以應對高并發請求。
- 安全性:網關必須能夠防止外部的惡意訪問,確保內部各個微服務的安全。
- 擴展性:網關是一個處理非業務功能的絕佳場所,必須能夠提供流量管控、協議轉發、日志監控等服務,同時能夠為以后對非業務功能的擴展提供良好的兼容性。
1.Zuul
Zuul作為Spring Cloud中的核心組件之一,充當API網關的重要角色,所有請求都可以通過Zuul達到后端的應用程序、服務。Zuul提供了動態路由、監控、彈性負載和安全等特性,其核心是一系列的Filter,其作用類似于Servlet框架中的Filter,或者AOP。
Zuul底層利用各種Filter實現了如下功能:
- 動態路由:根據需要將請求動態路由到后端集群。
- 身份認證和安全性:識別每個需要認證的資源,拒絕不符合要求的請求,如:鑒權。
- 統計監測:在服務邊界追蹤并統計數據,提供精確的統計監測視圖。
- 壓力測試:逐漸增加對集群的流量以了解其性能。
- 負載卸載:預先為每種類型的請求分配容量,當請求超過容量時自動丟棄。
- 靜態資源處理:直接在邊界返回某些響應。
基于上述這些功能特性,使得Zuul作為API網關的不二之選。Zuul的邏輯架構如下圖所示:
Zuul的過濾器之間是不直接通信的,而是通過一個RequestContext的類來進行數據傳統,RequestContext繼承ConcurrentHashMap,使用ThreadLocal變量來記錄每個Request需要傳遞的數據。
Zuul的過濾器是由Groovy來實現的,這些過濾器文件被存放在Zuul Server的特定目錄下,Zuul會定期輪詢這些目錄,修改過的過濾器會動態加載到Zuul Server中,以便過濾請求使用。
Zuul的大部分功能都是通過過濾器來實現的,其中定義了4種標準的過濾器類型(pre、route、post、error),以滿足應用于請求的不同階段。(如果想更清晰深入的了解Zuul,可以參考上圖的Zuul邏輯架構圖,并結合Zuul源碼深入研究下。)
2.traefik
在了解traefik之前,不妨先看看它的整體架構圖,如下所示:
從上圖不難看出,traefik充當了HTTP反向代理的角色,使得發布的服務變得輕松有趣。在微服務中,實質上是一個為了讓部署微服務變得更加便捷而誕生的HTTP反向代理、負載均衡工具。,它支持多種后臺 (Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, Zookeeper, BoltDB, Rest API, file…) 來自動化、動態的應用它的配置文件設置。
除了眾多功能之外,traefik的與眾不同之處還在于它會自動發現適合您服務的配置。無需維護和同步單獨的配置文件,一切都會自動,實時地進行(無需重新啟動,不會中斷連接)。使用traefik后,你可以將更多的精力、時間花費在開發和部署上面,而不是在配置和維護其工作狀態上。
特性:
- 高性能
- 無需安裝其他依賴,通過Go語言編寫的單一可執行文件
- 支持Restful API接口
- 多種后臺支持:Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd
- 后臺監控, 可以監聽后臺變化進而自動化應用新的配置文件設置
- 配置文件熱更新。(無需重啟)
- 正常結束http連接
- 后端斷路器
- 輪詢,rebalancer 負載均衡
- Rest Metrics
- 支持最小化官方docker鏡像
- 后臺支持SSL
- 前臺支持SSL(包括SNI)
- 清爽的AngularJS前端頁面
- 支持Websocket
- 支持HTTP/2
- 網絡錯誤重試
- 支持Let’s Encrypt (自動更新HTTPS證書)
- 高可用集群模式
3.OpenResty
OpenResty是一個基于Nginx與Lua的高性能Web平臺,其內部集成了大量精良的Lua庫、第三方模塊以及大多數的依賴項。用于方便地搭建能夠處理超高并發、擴展性極高的動態Web應用、Web服務和動態網關。
OpenResty通過匯聚各種設計精良的Nginx模塊(主要由OpenResty團隊自主開發),從而將Nginx有效地變成一個強大的通用Web應用平臺。這樣,Web 開發人員和系統工程師可以使用Lua腳本語言調動 Nginx支持的各種C以及Lua模塊,快速構造出足以勝任10K乃至 1000K以上單機并發連接的高性能Web應用系統。
OpenResty的目標是讓你的Web服務直接跑在Nginx服務內部,充分利用Nginx的非阻塞I/O模型,不僅僅對HTTP客戶端請求,甚至于對遠程后端諸如MySQL、PostgreSQL、Memcached以及Redis等都進行一致的高性能響應。
4.Kong
Kong是一個在Nginx中運行的Lua應用程序,并且可以通過lua-nginx模塊實現,Kong不是用這個模塊編譯Nginx,而是與OpenResty一起發布,OpenResty已經包含了lua-nginx-module,OpenResty不是 Nginx的分支,而是一組擴展功能的模塊。
是一個Api Gateway,通過插件的形式提供負載均衡,日志記錄,身份驗證,速率限制,轉換等功能。可以很輕松擴展功能,模塊化,可以運行在任何基礎設施上。
它的核心是實現數據庫抽象,路由和插件管理,插件可以存在于單獨的代碼庫中,并且可以在幾行代碼中注入到請求生命周期的任何位置。很方便地為路由和服務提供各種插件,網關所需要的基本特性,Kong都如數支持:
- 云原生:與平臺無關,Kong可以從裸機運行到Kubernetes。
- 動態路由:Kong的背后是OpenResty+Lua,所以從OpenResty繼承了動態路由的特性。
- 熔斷
- 健康檢查
- 日志:可以記錄通過Kong的HTTP,TCP,UDP請求和響應。
- 鑒權:權限控制,IP黑白名單,同樣是OpenResty的特性。
- SSL: 可以為基礎服務或API設置特定的SSL證書。
- 監控:Kong提供了實時監控插件。
- 認證:如支持HMAC, JWT, Basic, OAuth2.0等常用協議。
- 限流
- REST API:通過Rest API進行配置管理,從繁瑣的配置文件中解放。
- 可用性: 天然支持分布式。
- 高性能: 背靠非阻塞通信的nginx,性能自不用說。
- 插件機制: 提供眾多開箱即用的插件,且有易于擴展的自定義插件接口,用戶可以使用Lua自行開發插件。
上面這些特性中,反復提及了Kong背后的OpenResty,實際上,使用 Kong之后,Nginx可以完全摒棄,因為Kong的功能是Nginx的父集。
5.對比、總結
綜上對比,從開源社區活躍度和學習成本來看,無疑是Zuul和Traefik較好;從成熟度來看,較好的是Kong、Traefik;從性能角度來看,Kong要比其他幾個領先一些,從架構優勢的擴展性來看,Kong豐富的插件,而Zuul是完全需要自研各類Filter,但Zuul由于與Spring Cloud深度集成,使用度也很高。
六、服務注冊與發現
服務注冊與發現,是一個古老的話題,當應用開始脫離單機運行和訪問時,服務注冊與發現就誕生了。目前的網絡架構是每個主機都有一個獨立的IP地址,那么服務發現基本上都是通過某種方式獲取到服務所部署的IP地址。DNS協議是最早將一個網絡名稱翻譯為網絡IP的協議,在最初的架構選型中,DNS+LVS+Nginx基本可以滿足所有的RESTful服務的發現,此時服務的IP列表通常配置在Nginx或者LVS。后來出現了RPC服務,服務的上下線更加頻繁,人們開始尋求一種能夠支持動態上下線并且推送IP列表變化的注冊中心框架或組件。
現如今,各類服務注冊與發現的框架、組件很多(Zookeeper、Eureka、Consul、etcd等),在選擇上更是眼花繚亂。在服務注冊與發現的技術選型上,我覺得我們應該還是有一定遵循原則和關注要點的。通常可從以下幾個方面出發,進行重點關注、抉擇。
- 數據一致性
- 負載均衡
- 健康檢查
- 性能與容量
- 易用性
- 集群擴展性
- 用戶擴展性
七、配置中心
在微服務架構中,服務的數量以及配置信息的日益增多,比如各種服務器參數配置、各種數據庫訪問參數配置、各種環境下配置信息的不同、配置信息修改之后實時生效等等,傳統的配置文件方式或者將配置信息存放于數據庫中的方式已無法滿足開發人員對配置管理的要求,如:
- 安全性:配置跟隨源代碼保存在代碼庫中,容易造成配置泄漏。
- 時效性:修改配置,需要重啟服務才能生效。
- 局限性:無法支持動態調整:例如日志開關、功能開關。
在微服務架構中,使用配置中心之前,上述的問題或麻煩,你肯定也會遇到過,所以,是否引入配置中心,取決于你是否有下面的需求:
- 配置集中化統一管理
- 配置實時生效
一般完善的配置中心,都會從以下兩個方面設計出發,以發揮配置中心的作用。
1)配置實時生效
傳統的靜態配置方式要想修改某個配置只能修改之后重新發布應用,要實現動態性,可以選擇使用數據庫,通過定時輪詢訪問數據庫來感知配置的變化。輪詢頻率低感知配置變化的延時就長,輪詢頻率高,感知配置變化的延時就短,但比較損耗性能,需要在實時性和性能之間做折中。配置中心專門針對這個業務場景,兼顧實時性和一致性來管理動態配置。
2)配置管理
流程配置的權限管控、灰度發布、版本管理、格式檢驗和安全配置等一系列的配置管理相關的特性也是配置中心不可獲取的一部分。(這也算是配置中心的高級特性作用)
1.Spring Cloud Config
Spring Cloud Config作為Spring Cloud中的一個組件,其功能開放,可開發性強,常是各類配置中心自我研發的基石。
從Spring Cloud Config的源碼(spring-cloud-config-server)中,可以看出目前支持本地存儲、Git倉庫存儲、SVN倉庫存儲、數據庫存儲方式,其他存儲方式可參考源碼自行實現即可。
以Git存儲方式為例說明,Spring Cloud Config包含config-server、Git和Spring Cloud Bus三大組件:
- config-server提供給客戶端獲取配置。
- Git用于存儲和修改配置。
- Spring Cloud Bus通知客戶端配置變更。
本地測試模式下,Spring Cloud Bus和config-server需要部署一個節點,Git使用GitHub就可以。在生產環境中,Spring Cloud Config,config-server需要部署至少兩個節點。Spring Cloud Bus如果使用RabbitMQ,普通集群模式至少需要兩個節點。
Git服務如果使用GitHub就不用考慮高可用問題,如果考慮到安全性要自建Git私有倉庫,整體的成本比較高。Web服務可以部署多節點支持高可用,由于Git有數據的一致性問題,可以通過以下的方式來支持高可用:
- Git+Keepalived冷備模式,當主Git掛了可以馬上切到備Git。
- Git多節點部署,存儲使用網絡文件系統或者通過DRBD實現多個Git節點的數據同步。
2.Apollo
Apollo(阿波羅)是攜程框架部門研發的分布式配置中心,能夠集中化管理應用不同環境、不同集群的配置,配置修改后能夠實時推送到應用端,并且具備規范的權限、流程治理等特性,適用于微服務配置管理場景。
Apollo分為MySQL,Config Service,Admin Service,Portal四個模塊:
- MySQL:存儲Apollo元數據和用戶配置數據。
- Config Service:提供配置的讀取、推送等功能,客戶端請求都是落到Config Service上。
- Admin Service:提供配置的修改、發布等功能,Portal操作的服務就是Admin Service。
- Portal:提供給用戶配置管理界面。
本地測試Config Service,Admin Service,Portal三個模塊可以合并一起部署,MySQL單獨安裝并創建需要的表結構。在生產環境使用Apollo,Portal可以兩個節點單獨部署,穩定性要求沒那么高的話,Config Service和Admin Service可以部署在一起,數據庫支持主備容災。
3.Nacos
Nacos是一個更易于構建云原生應用的動態服務發現、配置管理和服務管理平臺。這正是Nacos官方給出的定義:
an easy-to-use dynamic service discovery, configuration and service management platform for building cloud native applications.
核心功能:
- 動態配置服務:
動態配置服務讓您能夠以中心化、外部化和動態化的方式管理所有環境的配置。動態配置消除了配置變更時重新部署應用和服務的需要。配置中心化管理讓實現無狀態服務更簡單,也讓按需彈性擴展服務更容易。
- 服務發現及管理:
動態服務發現對以服務為中心的(例如微服務和云原生)應用架構方式非常關鍵。Nacos支持DNS-Based和RPC-Based(Dubbo、gRPC)模式的服務發現。Nacos也提供實時健康檢查,以防止將請求發往不健康的主機或服務實例。借助Nacos,您可以更容易地為您的服務實現斷路器。
- 動態DNS服務:
通過支持權重路由,動態DNS服務能讓您輕松實現中間層負載均衡、更靈活的路由策略、流量控制以及簡單數據中心內網的簡單DNS解析服務。動態DNS服務還能讓您更容易地實現以DNS協議為基礎的服務發現,以消除耦合到廠商私有服務發現API上的風險。
Nacos部署需要Nacos Service和MySQL:
- Nacos Service:對外提供服務,支持配置管理和服務發現。
- MySQL:提供Nacos的數據持久化存儲。
單機模式下,Nacos可以使用嵌入式數據庫部署一個節點,就能啟動。如果對MySQL比較熟悉,想要了解整體數據流向,可以安裝MySQL提供給Nacos數據持久化服務。生產環境使用Nacos,Nacos服務需要至少部署三個節點,再加上MySQL主備。
4.對比、總結
整體來看,Nacos的部署結構比較簡單,運維成本較低。Apollo部署組件較多,運維成本比Nacos高。Spring Cloud Config易于定制化二次開發,生產高可用的成本最高。
總的來說,Apollo和Nacos相對于Spring Cloud Config的生態支持更廣,在配置管理流程上做的更好。Apollo相對于Nacos在配置管理做的更加全面,不過使用起來也要麻煩一些。Nacos使用起來相對比較簡潔,在對性能要求比較高的大規模場景更適合。
原文地址:https://mp.weixin.qq.com/s?__biz=MzA5MzUwOTY4NQ==&mid=2247488763&idx=1&sn=53eef5681236ce04ac52e2f6ee028485&chksm=905d95a1a72a1cb7e807a2bb4868b24c676a6ae577027e50173957e8ac41c14e8561301650cb&mpshare=1&