SpringBoot | 第二十九章:Dubbo的集成和使用 頂 原 薦

前言

今年年初時,阿里巴巴開源的高性能服務框架dubbo又開始了新一輪的更新,還加入了Apache孵化器。原先項目使用了spring cloud之後,已經比較少用dubbo。目前又抽調回原來的行業應用部門,可能還會使用dubbo進行服務調用。趁着編寫教材的機會來進行學習下。而且目前Dubbo也出了springbootstarter項目了,藉着SpringBoot的東風,集成起來很方便,基本上就一個依賴包引入的問題了。廢話不多說,開始吧~

一點知識

對於沒有接觸過Dubbo的同學,可以先了解下相關知識。

Dubbo簡介

Dubbo 是阿里巴巴公司一個開源的高性能服務框架,致力於提供高性能和透明化的 RPC 遠程服務調用方案,以及 SOA 服務治理方案,使得應用可通過高性能 RPC 實現服務的輸出、輸入功能和 Spring 框架無縫集成。Dubbo 包含遠程通訊、集羣容錯和自動發現三個核心部分。

它提供透明化的遠程方法調用,實現像調用本地方法一樣調用遠程方法,只需簡單配置,沒有任何 API 侵入。同時它具備軟負載均衡及容錯機制,可在內網替代 F5 等硬件負載均衡器,降低成本,減少單點。它可以實現服務自動註冊與發現,不再需要寫死服務提供方地址,註冊中心基於接口名查詢服務提供者的 IP 地址,並且能夠平滑添加或刪除服務提供者。

2011 年末,阿里巴巴在 GitHub 上開源了基於 Java 的分佈式服務治理框架 Dubbo,之後它成爲了國內該類開源項目的佼佼者,許多開發者對其表示青睞。同時,先後有不少公司在實踐中基於 Dubbo 進行分佈式系統架構。目前在 GitHub 上,它的 fork、star 數均已破萬。

Dubbo核心功能:

  • 遠程通訊,提供對多種基於長連接的 NIO 框架抽象封裝,包括多種線程模型,序列化,以及“請求-響應”模式的信息交換方式。
  • 集羣容錯,提供基於接口方法的透明遠程過程調用,包括多協議支持,以及軟負載均衡,失敗容錯,地址路由,動態配置等集羣支持。
  • 自動發現,基於註冊中心目錄服務,使服務消費方能動態的查找服務提供方,使地址透明,使服務提供方可以平滑增加或減少機器。

Dubbo架構

  1. 服務提供者 - 啓動時在指定端口上暴露服務,並將服務地址和端口註冊到註冊中心上
  2. 服務消費者 - 啓動時向註冊中心訂閱自己感興趣的服務,以便獲得服務提供方的地址列表
  3. 註冊中心 - 負責服務的註冊和發現,負責保存服務提供方上報的地址信息,並向服務消費方推送
  4. 監控中心 - 負責收集服務提供方和消費方的運行狀態,比如服務調用次數、延遲等,用於監控
  5. 運行容器 - 負責服務提供方的初始化、加載以及運行的生命週期管理

dubbo-architecture

部署階段

  • 服務提供者在指定端口暴露服務,並向註冊中心註冊服務信息。
  • 服務消費者向註冊中心發起服務地址列表的訂閱。

運行階段

  • 註冊中心向服務消費者推送地址列表信息。
  • 服務消費者收到地址列表後,從其中選取一個向目標服務發起調用。
  • 調用過程服務消費者和服務提供者的運行狀態上報給監控中心。

調用關係說明

  1. 服務容器負責啓動,加載,運行服務提供者。
  2. 服務提供者在啓動時,向註冊中心註冊自己提供的服務。
  3. 服務消費者在啓動時,向註冊中心訂閱自己所需的服務。
  4. 註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連接推送變更數據給消費者。
  5. 服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,如果調用失敗,再選另一臺調用。
  6. 服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心。

Dubbo特點

Dubbo 架構具有以下幾個特點,分別是連通性、健壯性、伸縮性、以及向未來架構的升級性。

連通性

  • 註冊中心負責服務地址的註冊與查找,相當於目錄服務,服務提供者和消費者只在啓動時與註冊中心交互,註冊中心不轉發請求,壓力較小
  • 監控中心負責統計各服務調用次數,調用時間等,統計先在內存彙總後每分鐘一次發送到監控中心服務器,並以報表展示
  • 服務提供者向註冊中心註冊其提供的服務,並彙報調用時間到監控中心,此時間不包含網絡開銷
  • 服務消費者向註冊中心獲取服務提供者地址列表,並根據負載算法直接調用提供者,同時彙報調用時間到監控中心,此時間包含網絡開銷
  • 註冊中心,服務提供者,服務消費者三者之間均爲長連接,監控中心除外
  • 註冊中心通過長連接感知服務提供者的存在,服務提供者宕機,註冊中心將立即推送事件通知消費者
  • 註冊中心和監控中心全部宕機,不影響已運行的提供者和消費者,消費者在本地緩存了提供者列表
  • 註冊中心和監控中心都是可選的,服務消費者可以直連服務提供者

健壯性

  • 監控中心宕掉不影響使用,只是丟失部分採樣數據
  • 數據庫宕掉後,註冊中心仍能通過緩存提供服務列表查詢,但不能註冊新服務
  • 註冊中心對等集羣,任意一臺宕掉後,將自動切換到另一臺
  • 註冊中心全部宕掉後,服務提供者和服務消費者仍能通過本地緩存通訊
  • 服務提供者無狀態,任意一臺宕掉後,不影響使用
  • 服務提供者全部宕掉後,服務消費者應用將無法使用,並無限次重連等待服務提供者恢復

伸縮性

  • 註冊中心爲對等集羣,可動態增加機器部署實例,所有客戶端將自動發現新的註冊中心
  • 服務提供者無狀態,可動態增加機器部署實例,註冊中心將推送新的服務提供者信息給消費者

升級性

當服務集羣規模進一步擴大,帶動IT治理結構進一步升級,需要實現動態部署,進行流動計算,現有分佈式服務架構不會帶來阻力。下圖是未來可能的一種架構:

dubbo-architucture-futures

節點角色說明

節點角色說明
Deployer自動部署服務的本地代理
Repository倉庫用於存儲服務應用發佈包
Scheduler調度中心基於訪問壓力自動增減服務提供者
Admin統一管理控制檯
Registry服務註冊與發現的註冊中心
Monitor統計服務的調用次數和調用時間的監控中心

大家可訪問官網文檔:http://dubbo.apache.org/zh-cn/docs/user/quick-start.html,裏面有詳細說明和使用說明的。這裏就不再闡述了。

Dubbo集成和使用

基於官方的incubator-dubbo-spring-boot-project項目,在SpringBoot中集成起來很簡單。

注意:由於本系列還是使用1.5.x版本進行講解,所以使用的版本爲0.1.x。若使用SpringBoot2.x的同學,可以使用0.2.x版本。

官方說明

這裏爲了方便,直接創建了一個接口工程,spring-boot-dubbo-api

IHelloService.java

/**
 * 定義一個接口
 * @author oKong
 *
 */
public interface IHelloService {
    
    String hello(String name);

}

服務提供者

創建一個spring-boot-dubbo-provider工程。 0.引入pom依賴。

        <!-- 引入api -->
        <dependency>
            <groupId>cn.lqdev.learning</groupId>
            <artifactId>spring-boot-dubbo-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!-- 引入dubbo依賴 -->
        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>0.1.1</version>
        </dependency>
        <!-- 引入redis作爲註冊中心 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

注意:這裏直接選用了redis作爲註冊中心使用。默認是zookeeper

1.編寫接口實現類。 HelloServiceImpl.java

/**
 * 定義一個服務實現類
 * @author oKong
 *
 */
// 這裏注意 此類@service是dubbo的
@Service(
        version = "${demo.service.version}", //版本
        application = "${dubbo.application.id}", //應用ID
        protocol = "${dubbo.protocol.id}", //協議id
        registry = "${dubbo.registry.id}")//註冊中心id
@Slf4j
public class HelloServiceImpl implements IHelloService {
    
    @Override
    public String hello(String name) {
        log.info("dubbo提供者,參數name:{}", name);
        return "hello " + name + ",this is a dubbo provider!";
    }

}

說明下:這裏的@Service是包路徑com.alibaba.dubbo.config.annotation.Service下的註解類,其指定了接口版本、協議id、註冊中心id等基本信息。這裏注意還是版本號有用,因爲會一個接口多版本共存問題,所以一般上都會設置版本信息的。 2.設置配置文件信息,添加dubbo相關信息,比如註冊中心類型,地址等。

# 應用名稱 便於識別
dubbo.application.id=spring-boot-dubbo-provider
dubbo.application.name=spring-boot-dubbo-provider

server.port=8686


# 設置版本
demo.service.version=1.0.0

#協議 可選dubbo redis、http、thrift等
dubbo.protocol.id=dubbo
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

#設置掃描路徑 被註解@service和@Reference 等
dubbo.scan.basePackages=cn.lqdev.learning.springboot.dubbo.provider.service

# 註冊中心配置
dubbo.registry.id=okong-registry
#註冊中心類型 這裏使用redis作爲註冊中心
# zookeeper://127.0.0.1:2181
dubbo.registry.address=redis://127.0.0.1:6379
# 設置用戶名密碼 若有的話
#dubbo.registry.username=oKong
#dubbo.registry.password=oKong
# 設置redis參數
# 連接池中的最大空閒連接
dubbo.registry.parameters.max.idle=8
# 連接池最大連接數(使用負值表示沒有限制)
dubbo.registry.parameters.max-active=8
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
dubbo.registry.parameters.max-wait=-1
# 連接池中的最大空閒連接
dubbo.registry.parameters.max-idle=8
# 連接池中的最小空閒連接
dubbo.registry.parameters.min-idle=0

注意:這裏爲了方便,直接使用了Redis作爲了註冊中心。對於redis連接相關配置參數,可以通過dubbo.registry.parameters.xxx的形式來進行設置,由於parameters是個Map對象,所以添加的key是不會進行大小寫轉換的,填寫了什麼就是什麼。具體的registry配置對象,可以查看com.alibaba.dubbo.config.RegistryConfig類。而對於redis相關參數配置,可以查看com.alibaba.dubbo.registry.redis.RedisRegistry類。

RedisRegistry

其他的註冊中心,也是類似的,大家可在包com.alibaba.dubbo.registry找到都要的註冊中心配置類。

3.啓動類編寫。

DubboProviderApplication.java

/**
 * dubbo-提供者
 * @author oKong
 *
 */
@SpringBootApplication
@Slf4j
public class DubboProviderApplication {

    public static void main(String[] args) throws Exception {
        //由於dubbo提供者只是單純提供服務的 可以爲一個非web環境
        new SpringApplicationBuilder(DubboProviderApplication.class).web(false).run(args);
        log.info("spring-boot-dubbo-provider啓動!");
    }

}

4.啓動應用,可以訪問下redis服務,可以看見已經有服務列表信息了。

redis

服務消費者

創建spring-boot-dubbo-consumer工程。 0.引入pom依賴

    <!-- 引入api -->
        <dependency>
            <groupId>cn.lqdev.learning</groupId>
            <artifactId>spring-boot-dubbo-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!-- 引入dubbo依賴 -->
        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>0.1.1</version>
        </dependency>
        <!-- 引入redis作爲註冊中心 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

1.配置文件添加註冊中心及服務版本相關信息

# 應用名稱 便於識別
dubbo.application.id=spring-boot-dubbo-consumer
dubbo.application.name=spring-boot-dubbo-consumer

server.port=9696

#設置掃描路徑 被註解@service和@Reference 等
dubbo.scan.basePackages=cn.lqdev.learning.springboot.dubbo.consumer

# 註冊中心配置
dubbo.registry.id=okong-registry
#註冊中心類型 這裏使用redis作爲註冊中心
# zookeeper://127.0.0.1:2181
dubbo.registry.address=redis://127.0.0.1:6379
# 設置用戶名密碼 若有的話
#dubbo.registry.username=oKong
#dubbo.registry.password=oKong
# 設置redis參數
# 連接池中的最大空閒連接
dubbo.registry.parameters.max.idle=8
# 連接池最大連接數(使用負值表示沒有限制)
dubbo.registry.parameters.max-active=8
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
dubbo.registry.parameters.max-wait=-1
# 連接池中的最大空閒連接
dubbo.registry.parameters.max-idle=8
# 連接池中的最小空閒連接
dubbo.registry.parameters.min-idle=0

2.啓動類編寫

DubboConsumerApplication.java

/**
 * dubbo-消費者實例
 * @author oKong
 *
 */
@SpringBootApplication
@Slf4j
public class DubboConsumerApplication {
    
    public static void main(String[] args) throws Exception {
        SpringApplication.run(DubboConsumerApplication.class, args);
        log.info("spring-boot-dubbo-consumer啓動!");
    }
}

3.編寫一個restapi接口服務,進行服務調用。

/**
 * 調用實例
 * @author oKong
 *
 */
@RestController
@Slf4j
public class DemoController {

    /**
     * 申明爲一個reference,其實就是設置一個bean類了,
     * 將原來xml配置替換成註解而已
     * <dubbo:reference id=“xxxService” interface=“com.xxx.XxxService” />
     */
    @Reference(version = "1.0.0")
    IHelloService helloService;
    
    @GetMapping("/hello")
    public String hello(String name) {
        log.info("調用提供者服務,參數name:{}", name);
        return helloService.hello(name);
    }
}

4.啓動應用,訪問:http://127.0.0.1:9696/hello?name=oKong ,可以看見服務調用成功了。

服務調用

監控後臺

官方監控默認支持了zookeeper。而且官方文檔也說了,對於redis橋接實現只爲開源版本提供,其可靠性依賴於 Redis 本身的可靠性。建議大家還是使用zookeeper吧,redis還是作爲緩存使用吧。

監控臺地址:https://github.com/apache/incubator-dubbo-ops 大家可自行安裝說明進行編譯運行下。

新的監控界面:

加入了Apache孵化器後,界面都是英文的了。。。還是原來的看的舒服呀!

參考資料

  1. http://jm.taobao.org/2018/06/13/%E5%BA%94%E7%94%A8/

  2. http://dubbo.apache.org/zh-cn/docs/user/preface/architecture.html

總結

本章節主要介紹了dubbo的集成和簡單的使用。具體其他的使用其實和原先是一樣的,並沒有什麼區別。建議大家還是去看看官方文檔,目前改版後內容豐富多了,乾貨很多,建議還是去看看。這下終於是中文版的了,看的不頭疼了,⊙﹏⊙‖∣

最後

目前互聯網上很多大佬都有SpringBoot系列教程,如有雷同,請多多包涵了。原創不易,碼字不易,還希望大家多多支持。若文中有所錯誤之處,還望提出,謝謝。

老生常談

  • 個人QQ:499452441
  • 微信公衆號:lqdevOps

公衆號

個人博客:http://blog.lqdev.cn

完整示例:https://github.com/xie19900123/spring-boot-learning/tree/master/chapter-29

原文地址:http://blog.lqdev.cn/2018/09/28/springboot/chapter-twenty-nine/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章