微服務框架方案對比

一、什么是微服務

微服務架構是一種架構模式,它提倡將單一應用程序劃分成一組小的服務,服務之間互相協調、互相配合,為用戶提供最終價值。

系統中的各個微服務可被獨立部署,各個微服務之間是松耦合。

二、微服務的特點

  • 復雜度可控

    每一個微服務專注于單一功能

  • 獨立部署

    當某個微服務發生變更時無需編譯、部署整個應用

  • 技術選型靈活

    技術選型是去中心化的

  • 容錯

    故障會被隔離在單個服務中

  • 擴展

    每個服務可以根據實際需求獨立進行擴

三、主流的解決方案

  • Dubbo
  • SpringCloud

四、Dubbo VS SpringCloud

4.1、總體架構

  • Dubbo


    image.png
  • Provider
    暴露服務的提供方,可通過jar或者容器的方式啟動服務

  • Consumer
    調用遠程服務的服務消費方

  • Registry
    服務注冊中心和發現中心

  • Monitor
    統計服務和調用次數,調用時間監控中心

  • Container
    服務運行的容器

  • SpringCloud


    image.png
  • Service Provider
    暴露服務的提供方

  • Service Consumer
    調用遠程服務的服務消費方

  • EureKa Server
    服務注冊中心和服務發現中心

結論:
整體架構上來看,二者模式接近,都需要需要服務提供方,注冊中心,服務消費方。

4.2、功能擴展

功能要素 Dubbo SpringCloud
服務注冊中心 Zookeeper、Redis Netflix Eureka
服務調用方式 RPC Rest API
服務網關 暫無 Netflix Zuul
斷路(熔斷)器 暫不完善 Netflix Hystrix
配置中心 暫無 Spring Cloud Config
調用鏈追蹤 暫無 Spring Cloud Sleuth
消息總線 暫無 Spring Cloud Bus
數據流 暫無 Spring Cloud Stream 封裝了與Redis,Rabbit、Kafka等發送接收消息
批量任務 暫無 Spring Cloud Task
  1. Dubbo只是實現了服務治理

  2. SpringCloud子項目分別覆蓋了微服務架構體系下的方方面面,服務治理只是其中的一個方面

  3. Dubbo額外提供了Filter擴展,對于上述“暫無”的部分,都可以通過擴展Filter來完善

  • 配置中心

可以使用淘寶的diamond、百度的disconf來實現分布式配置管理

  • 服務跟蹤

可以使用京東開源的Hydra,或者擴展Filter用Zipkin來做服務跟蹤

  • 批量任務

可以使用當當開源的Elastic-Job、tbschedule

結論: 從功能擴展上來看,Spring Cloud 更勝一籌,在開發過程中只要整合Spring Cloud的子項目就可以順利的完成各種組件的融合,而Dubbo缺需要通過實現各種Filter來做定制,開發成本以及技術難度略高。

4.3、通訊協議

  • Dubbo
  1. Dubbo使用RPC通訊協議

  2. Dubbo缺省協議采用單一長連接和NIO異步通訊,適合于小數據量大并發的服務調用,以及服務消費者機器數遠大于服務提供者機器數的情況

  • SpringCloud

Spring Cloud 使用HTTP協議的REST API

結論: dubbo支持各種通信協議,而且消費方和服務方使用長鏈接方式交互,通信速度上略勝Spring Cloud,如果對于系統的響應時間有嚴格要求,長鏈接更合適。

4.4、服務依賴方式

比較維度 Dubbo SpringCloud
交互方式 定義DTO JSON方式
調用方式 RPC HTTP
代碼入侵 配置xml,無代碼入侵 注解配置,有代碼入侵
依賴情況 調用方與提供方強依賴 無依賴,可跨平臺
版本管理 需要制定完善的版本管理機制 省略了版本管理的問題,但是具體字段含義需要統一管理
  • Dubbo


    image.png
  1. 服務提供方與消費方通過接口的方式依賴,服務調用設計如下
  • Interface層:
    服務接口層,定義了服務對外提供的所有接口

  • Molel層:
    服務的DTO對象層

  • business層:
    業務實現層,實現interface接口并且和DB數據庫進行交互

  1. 通過maven的install & deploy命令把Interface和Model層發布到倉庫中,服務調用方只需要依賴Interface和model層即可,然后通過xml配置方式即可很方便地接入dubbo,對代碼無入侵
  • SpringCloud
    image.png

服務提供方和服務消費方通過json方式交互,因此只需要定義好相關json字段即可,消費方和提供方無接口依賴。通過注解方式來實現服務配置,對于程序有一定入侵

結論:

  1. Dubbo服務依賴略重,需要有完善的版本管理機制,但是程序入侵少。

  2. Spring Cloud通過Json交互,省略了版本管理的問題,但是具體字段含義需要統一管理,自身Rest API方式交互,為跨平臺調用奠定了基礎。

4.5、組件運行流程

  • Dubbo


    image.png
  • gateWay
    前置網關,具體業務操作,gateWay通過dubbo提供的負載均衡機制自動完成

  • Service
    原子服務,只提供該業務相關的原子服務

  • Zookeeper
    原子服務注冊到zk上

  • SpringCloud


    image.png
  1. 所有請求都統一通過API網關(Zuul)來訪問內部服務

  2. 網關接收到請求后,從注冊中心(Eureka)獲取可用服務

  3. 由Ribbon進行均衡負載后,分發到后端的具體實例

  4. 微服務之間通過Feign進行通信處理業務

  5. Hystrix負責處理服務超時熔斷

  6. Turbine監控服務間的調用和熔斷相關指標

結論:

  1. 業務部署方式相同,都需要前置一個網關來隔絕外部直接調用原子服務的風險

  2. Dubbo需要自己開發一套API網關,技術難度稍大

  3. 而Spring Cloud則可以通過Zuul配置即可完成網關定制,比較便捷

  4. 使用方式上Spring Cloud略勝一籌

五、目前的現狀

  • Dubbo
  1. 目前以來,一直使用的dubbo,對我們團隊而言,dubbo相對比較熟悉

  2. 公司架構師大部分出自阿里系,對dubbo比較熟悉,出現問題比較好解決

  3. 公司其他小組也是使用的dubbo,日后對接比較方便

  • SpringCloud
  1. 團隊成員對于此技術棧比較陌生,少數隊員熟悉

  2. 后面上線倘若出現問題,不太容易解決

  3. 技術棧不統一,后面與其他團隊對接不太方便

六、Dubbo與SpringCloud共存方案

首先,我們需要對相應的工程進行調整,并接入SpringCloud,使得服務在保持原有工作的基礎上,也同時要能夠接到Eureka進行服務提供,主要包含兩部分:

  1. 使原有的dubbo服務提供Restful規范接口

  2. 服務調用方接入調整

6.1、共存實現方式

  1. 獨立共存

保持原dubbo的service實現不變,額外基于service改造提供Restful接口

  1. 基于Feign進行切換

2.1 在原有dubbo的service接口上配置feign支持

2.2 修改原dubbo的service實現類,對外提供Restful接口

6.2、獨立共存方案

  • 初始狀態結構

服務提供者(provider)往注冊中心(registry)注冊服務,服務消費者(consumer)從注冊中心訂閱服務

image.png
  • 共存狀態結構

保持原dubbo的service實現不變,額外基于service改造提供Restful接口

image.png

6.3、基于Feign進行切換

1、修改原dubbo provider,同時向dubbo registry和eureka注冊相同服務

2、修改原dubbo consumer,根據配置方式支持dubbo或http調用

image.png
具體實現思路
  1. 修改原dubbo服務定義的api接口,支持feign調用
@FeignClient("demo")
public interface DemoService {

    @RequestMapping(value = "/{version}/pt/demos/{appId}", method = RequestMethod.GET)
    Response<Integer> post(@PathVariable("appId") String appId);
}
  1. 修改原dubbo服務的實現類,添加@RestController對外提供Restful接口
@Service
@RestController
public class DemoServiceImpl implements DemoService {

    @Override
    public Response<Integer> post(String appId) {
        return null;
    }
}
  1. 消費者需要切換調用方式,如果原來的dubbo消費者使用了@Refrence注解,直接將其更改為@Autowoired即可。如果使用的是xml配置refrence則直接注解即可。
@Reference
private DemoService demoService;

//更改為
@Autowired
private DemoService demoService;

七、RPC調用的痛點

1. 服務提供方與調用方接口依賴方式太強

  • Dubbo

1、每個微服務都定義了抽象接口,并且每次并更之后都需要發布到倉庫

2、調用方與提供方存在強依賴,需要嚴格地進行版本管理,否則容易出現調用與服務方版本不一致而導致無法編譯成功

3、本地開發環境也會受到影響,往往一個應用可能需要依賴一系列的上游應用,每當上游應用發生修改,則需要經常更新代碼并且install之后才能進行后續開發

總結:
需要嚴格的版本管理制度或者開發一些自動化工具否則,依賴關系會成為一大噩夢

  • SpringCloud

1、REST接口相比RPC更為輕量化,服務提供方和調用方的依賴只是依靠一紙契約,不存在代碼級別的強依賴

2、然而REST接口也有痛點,因為接口定義過輕,很容易導致定義文檔與實際實現不一致導致服務集成時的問題

3、可以通過每個服務都整合swagger,使得每個服務的代碼與文檔一體化,從而解決上述問題

總結:
在分布式環境下,REST方式的服務依賴要比RPC方式的依賴更為靈活

2. 服務對平臺敏感,難以簡單復用

  1. 通常我們在提供對外服務時,都會以REST的方式提供出去,這樣可以實現跨平臺的特點,任何一個語言的調用方都可以根據接口定義來實現

  2. 在Dubbo中我們要提供REST接口時,不得不實現一層代理,用來將RPC接口轉換成REST接口進行對外發布

  3. 若我們每個服務本身就以REST接口方式存在,當要對外提供服務時,主要在API網關中配置映射關系和權限控制就可實現服務的復用了

八、Zuul服務網關

1、針對某個功能,客戶端在微服務架構的情況下需要請求多個模塊接口

2、針對于身份認證、日志、流量控制等公共模塊每個微服務都需要做一遍,不利于業務與非業務的拆分

針對以上這些問題,Zuul可完美解決

  • 所有的微服務對外只有一個接口,我們只需訪問一個網關地址,即可由網關將所有的請求代理到不同的服務中
  • 客戶端只需要知道網關而不需要知道具體模塊的地址,所有服務由網關對外提供
  • 身份認證類的東西單獨抽象出來,業務模塊只做業務

九、后續思考

  1. 目前主要存在什么問題?
  2. 是否有必要引進SpringCloud?
  3. 如果引進了SpringCloud,后續可能會出現哪些問題?

十、原文參考

  1. https://blog.csdn.net/qq_41587754/article/details/80133775
  2. http://springcloud.cn/view/254
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容