Spring Boot 中使用 Dubbo 詳解

搜雲庫技術團隊發表於2017-10-28

Dubbo是阿里巴巴SOA服務化治理方案的核心框架,每天為2,000+個服務提供3,000,000,000+次訪問量支援,並被廣泛應用於阿里巴巴集團的各成員站點。Dubbo是一個分散式服務框架,致力於提供高效能和透明化的RPC遠端服務呼叫方案,以及SOA服務治理方案。

Dubbo 簡介

Dubbo 是什麼?

Dubbo是一個分散式服務框架,致力於提供高效能和透明化的RPC遠端服務呼叫方案,以及SOA服務治理方案。簡單的說,dubbo就是個服務框架,如果沒有分散式的需求,其實是不需要用的,只有在分散式的時候,才有dubbo這樣的分散式服務框架的需求,並且本質上是個服務呼叫的東東,說白了就是個遠端服務呼叫的分散式框架

其核心部分包含:

1.遠端通訊: 提供對多種基於長連線的NIO框架抽象封裝,包括多種執行緒模型,序列化,以及“請求-響應”模式的資訊交換方式。
2.叢集容錯: 提供基於介面方法的透明遠端過程呼叫,包括多協議支援,以及軟負載均衡,失敗容錯,地址路由,動態配置等叢集支援。
3.自動發現: 基於註冊中心目錄服務,使服務消費方能動態的查詢服務提供方,使地址透明,使服務提供方可以平滑增加或減少機器。

Dubbo 能做什麼?

1.透明化的遠端方法呼叫,就像呼叫本地方法一樣呼叫遠端方法,只需簡單配置,沒有任何API侵入。
2.軟負載均衡及容錯機制,可在內網替代F5等硬體負載均衡器,降低成本,減少單點。
3.服務自動註冊與發現,不再需要寫死服務提供方地址,註冊中心基於介面名查詢服務提供者的IP地址,並且能夠平滑新增或刪除服務提供者。

Dubbo 的架構

架構圖

節點角色說明

節點 角色說明
Provider 暴露服務的服務提供方
Consumer 呼叫遠端服務的服務消費方
Registry 服務註冊與發現的註冊中心
Monitor 統計服務的呼叫次調和呼叫時間的監控中心
Container 服務執行容器

Dubbo提供三個關鍵功能,包括基於介面的遠端呼叫,容錯和負載平衡以及自動服務註冊和發現

呼叫關係說明

1.服務容器負責啟動,載入,執行服務提供者。
2.服務提供者在啟動時,向註冊中心註冊自己提供的服務。
3.服務消費者在啟動時,向註冊中心訂閱自己所需的服務。
4.註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連線推送變更資料給消費者。
5.服務消費者,從提供者地址列表中,基於軟負載均衡演算法,選一臺提供者進行呼叫,如果呼叫失敗,再選另一臺呼叫。
6.服務消費者和提供者,在記憶體中累計呼叫次數和呼叫時間,定時每分鐘傳送一次統計資料到監控中心。

Dubbo 特點

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

連通性

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

健狀性

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

伸縮性

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

升級性

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

未來可能的一種架構

節點角色說明

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

快速開始

Dubbo 採用全 Spring 配置方式,透明化接入應用,對應用沒有任何 API 侵入,只需用 Spring 載入 Dubbo 的配置即可,Dubbo 基於 Spring 的 Schema 擴充套件進行載入。

環境安裝

任選其一

CentOs7.3 搭建 ZooKeeper-3.4.9 單機服務
CentOs7.3 搭建 ZooKeeper-3.4.9 Cluster 叢集服務

Github 程式碼

程式碼我已放到 Github ,匯入spring-boot-dubbo 專案

github github.com/souyunku/sp…

Maven依賴

在專案中新增 dubbo 依賴

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.5.6</version>
</dependency>
複製程式碼

定義服務介面

專案:dubbo-api

public interface DemoService {
    String sayHello(String name);
}
複製程式碼

服務提供方

專案:dubbo-provider,在服務提供方實現介面

@Service("demoService")
public class DemoServiceImpl implements DemoService {

    @Override
    public String sayHello(String name) {
        System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
        return "Hello " + name + ", response form provider: " + RpcContext.getContext().getLocalAddress();
    }
}
複製程式碼

載入 dubbo 配置

@Configuration
@PropertySource("classpath:dubbo.properties")
@ImportResource({"classpath:dubbo/*.xml"})
public class PropertiesConfig {
}
複製程式碼

在提供方增加暴露服務配置 : <dubbo:service>

dubbo-provider.xml

<!-- 宣告需要暴露的服務介面 -->
<dubbo:service interface="io.ymq.dubbo.api.DemoService" ref="demoService"/>
複製程式碼

服務消費方

專案:dubbo-consumer ,消費消費遠端方法

@Service("consumerDemoService")
public class ConsumerDemoService {

    @Autowired
    private DemoService demoService;

    public void sayHello(String name) {
        String hello = demoService.sayHello(name); // 執行消費遠端方法
        System.out.println(hello); // 顯示呼叫結果
    }
	
}
複製程式碼

載入 dubbo 配置

@Configuration
@PropertySource("classpath:dubbo.properties")
@ImportResource({"classpath:dubbo/*.xml"})
public class PropertiesConfig {
}
複製程式碼

在消費方增加引用服務配置: <dubbo:reference>

dubbo-consumer.xml

<!-- 增加引用遠端服務配置 可以和本地bean一樣使用demoService -->
<dubbo:reference id="demoService" check="false" interface="io.ymq.dubbo.api.DemoService"/>
複製程式碼

遠端服務 Dubbo 配置

專案:dubbo-provider ,dubbo-consumer 一樣配置

dubbo.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 提供方應用資訊,用於計算依賴關係 -->
    <dubbo:application name="${spring.application.name}"  />

    <!-- 使用multicast廣播註冊中心暴露服務地址 -->
    <dubbo:registry protocol="zookeeper" address="${zookeeper.connect}"  file="${dubbo.cache}"/>

    <!-- 用dubbo協議在20880埠暴露服務 -->
    <dubbo:protocol name="dubbo" port="${dubbo.protocol.port}"  threadpool="${dubbo.protocol.threadpool}"  threads="${dubbo.protocol.threads}"/>

    <!-- 提供方的預設值,當ProtocolConfig和ServiceConfig某屬性沒有配置時,採用此預設值,可選。-->
    <dubbo:provider connections="${dubbo.provider.connections}" timeout="${dubbo.provider.timeout}" retries="${dubbo.provider.retries}" version="${dubbo.provider.version}" />

    <!-- 消費方預設配置,當ReferenceConfig某屬性沒有配置時,採用此預設值,可選。-->
    <dubbo:consumer version="${dubbo.provider.version}" />

    <!-- 監控中心配置,用於配置連線監控中心相關資訊,可選。-->
    <dubbo:monitor protocol="registry"/>

</beans>
複製程式碼

dubbo.properties

#########################################################
# dubbo config
#暴露服務埠
dubbo.protocol.port=20880
#提供方超時時間
dubbo.provider.timeout=10000
#提供方版本
dubbo.provider.version=1.0
#表示該服務使用獨的五條條長連
dubbo.provider.connections=5
# 固定大小執行緒池,啟動時建立執行緒,不關閉,一直持有。(預設)
dubbo.protocol.threadpool=fixed
# 執行緒數量
dubbo.protocol.threads=500
#配置重試次數,最好只用於讀的重試,寫操作可能會引起多次寫入  預設retries="0"
dubbo.provider.retries=0
# dubbo快取檔案
dubbo.cache=/data/dubbo/cache/dubbo-provider
#########################################################
# zookeeper config
zookeeper.connect=127.0.0.1:2181
複製程式碼

測試 Dubbo

  1. 該介面需單獨打包,在服務提供方和消費方共享 ↩
  2. 對服務消費方隱藏實現 ↩
  3. 也可以使用 IoC 注入 ↩

啟動 ZooKeeper

啟動服務

/opt/zookeeper-3.4.9/bin/zkServer.sh start
複製程式碼

啟動提供方服務

package io.ymq.dubbo.provider.run;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

/**
 * 描述:啟動提供方服務
 *
 * @author yanpenglei
 * @create 2017-10-27 11:49
 **/
@SpringBootApplication
@ComponentScan(value = {"io.ymq.dubbo"})
public class Startup {

    public static void main(String[] args) {
        SpringApplication.run(Startup.class, args);
    }
}

複製程式碼

測試消費遠端服務

package io.ymq.dubbo.test;

import io.ymq.dubbo.consumer.run.Startup;
import io.ymq.dubbo.consumer.service.ConsumerDemoService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * 描述: 測試消費遠端服務
 *
 * @author yanpenglei
 * @create 2017-10-27 14:15
 **/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Startup.class)
public class ConsumerTest {

    @Autowired
    private ConsumerDemoService consumerDemoService;

    @Test
    public void sayHello(){
        consumerDemoService.sayHello("Peng Lei");
    }
}
複製程式碼

響應:

[15:54:00] Hello Peng Lei, request from consumer: /10.4.82.6:63993
複製程式碼

程式碼我已放到 Github ,匯入spring-boot-dubbo 專案

github github.com/souyunku/sp…

Contact

  • 作者:鵬磊
  • 出處:www.ymq.io
  • Email:admin@souyunku.com
  • 版權歸作者所有,轉載請註明出處
  • Wechat:關注公眾號,搜雲庫,專注於開發技術的研究與知識分享

關注公眾號-搜雲庫
搜雲庫

相關文章