Springboot整合Dubbo+Zookeeper

一:什麼是Dubbo

Dubbo是一款高性能、輕量級的開源Java RPC框架,
它提供了三大核心能力:面向接口的遠程方法調用,智能容錯和負載均衡,以及服務自動註冊和發現。
即實現了多個獨立應用之間的解耦且可以遠程調用對方的服務

二、爲什麼需要 dubbo

很多時候,因爲項目需要用到分佈式架構,所以就引用了dubbo這項技術,但是至於爲什麼我們需要用到這個技術
可能自身並不是很瞭解,但是,其實瞭解技術的來由及背景知識,對於理解一項技術還是有幫助的,
在以前,我們只需要一個服務器,將程序全部打包好就可以,但是,隨着流量的增大,常規的垂直應用架構已無法應對,所以,架構就發生了演變。

所需演變的方面
1 單一應用架構
2 應用和數據庫單獨部署
3 應用和數據庫集羣部署
4 數據庫壓力變大,讀寫分離
5 使用緩存技術加快速度
6 數據庫分庫分表
7 應用分爲不同的類型拆分

發展到這個階段的時候,我們發現,應用與應用之間的關係已經十分的複雜了,就會出現以下幾個問題(以下摘錄於官網):

① 當服務越來越多時,服務 URL 配置管理變得非常困難,F5 硬件負載均衡器的單點壓力也越來越大。
② 當進一步發展,服務間依賴關係變得錯蹤複雜,甚至分不清哪個應用要在哪個應用之前啓動,架構師都不能完整的描述應用的架構關係。
③ 接着,服務的調用量越來越大,服務的容量問題就暴露出來,這個服務需要多少機器支撐?什麼時候該加機器?

爲了解決這由於架構的演變所產生的問題幾個問題,於是,dubbo 產生了。當然,解決這個問題的技術不止 dubbo 。

三、關鍵點介紹:

1.註冊與發現  
    Dubbo使用zookeeper做服務的註冊中心,就是服務的提供者以臨時節點的形式將服務Server信息註冊保存到Zookeeper的dubbo目錄下
的provider的節點下,供消費者發現調用。

2.負載均衡
    Dubbo支持負載均衡策略,就是同一個Dubbo服務被多臺服務器啓用後,會在Zookeeper提供者節點下顯示多個相同接口名稱節點。
    消費者在調用Dubbo負載均衡服務時,採用權重的算法策略選擇具體某個服務器上的服務,權重策略以*2倍數設置。

3.容錯機制
    Dubbo的提供者在Zookeeper上使用的是臨時節點,一旦提供者所在服務掛掉,該節點的客戶端連接將會關閉,故節點自動消失。所以消費者調用接口時將不會輪詢到已經掛掉的接口上(延遲例外)。

4.Dubbo協議
    Dubbo常用協議有兩種:dubbo、hessian
    dubbo:
      Dubbo 缺省協議是dubbo協議,採用單一長連接和 NIO 異步通訊,適合於小數據量大併發的服務調用,以及服務消費者機器數遠大於服務提供者機器數的情況。

hessian:
      Hessian底層採用Http通訊(同步),採用Servlet暴露服務。適用於傳入傳出參數數據包較大,消費者併發量少,提供者較多,可傳文件。

5.Dubbo容器
    Dubbo在java jvm中有自己的容器,和Spring IOC的bean一樣,將服務對象保存到自己的容器中。

6.監控中心
    監控中心主要是用來服務監控和服務治理。
    服務治理包含:負載均衡策略、服務狀態、容錯、路由規則限定、服務降級等。具體可以下載Dubbo監控中心客戶端查看與設置。
dubbo監控中心下載和搭建啓動參考網址https://blog.csdn.net/a704397849/article/details/91904842

四、節點角色說明

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

看了這幾個概念後似乎發現,其實 Dubbo 的架構也是很簡單的(其實現細節是複雜的),爲什麼這麼說呢,有沒有發現,
其實很像"生產者-消費者"模型。只是在這種模型上,加上了註冊中心和監控中心,用於管理提供方提供的url,以及監控和管理整個過程

那麼dubbo發佈-訂閱的過程是怎樣的呢?

1、啓動容器,加載,運行服務提供者。
2、服務提供者在啓動時,在註冊中心發佈註冊自己提供的服務。
3、服務消費者在啓動時,在註冊中心訂閱自己所需的服務

容器如何啓動呢?

即java中整合了dubbo,在spirngboot的啓動類上加一個啓動的註解,服務啓動即自動開啓容器

當然作爲一個類似於中間件的dubbo框架,肯定也有對它某些配置自定義的方式 如

1、註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連接推送變更數據給消費者。
2、服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,如果調用失敗,再選另一臺調用。
3、服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心。
這些均可在java配置文件中進行配置,下面在詳細講述

五、zookeeper

欲實現dubbo架構先要搭建zookeeper集羣作爲服務註冊發現中心,安裝集羣步驟參考網址https://blog.csdn.net/weixin_43784880/article/details/104428651

此前就完成了dubbo-admin和zookepper集羣的搭建,啓動後進行下面步驟

六、SpringBoot整合Dubbo和Zookeeper

先說明後不亂:

這裏創建了一個主工程dubbo-hotels,其下包含了api、dubbo-provider、dubbo-customer
api: 主要存放公共實體類、需要遠程調用的服務接口、也可以放一些公用的工具類工程
dubbo-provider: 服務提供工程 將接口實現類的服務暴露出去
dubbo-customer: 服務調用工程 遠程從zookeeper調用提供者暴露的服務
切記:因爲服務接口只是寫在api工程中,所以dubbo-provider、dubbo-customer兩個工程都需要在pom文件中引入api的jar包,下面會一一闡述

父工程
1、先創建一個springboot主工程 dubbo-hotels
主工程添加依賴如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
<!--    添加springboot父級依賴-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <!--自定義該工程的jar包的座標-->
    <groupId>com.hotels</groupId>
    <artifactId>dubbo-hotels</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>dubbo-hotels</name>

    <modules>
        <!-- 服務消費者工程 -->
        <module>dubbbo-customer</module>
        <module>hotel-customer</module>
        <!--  服務提供者工程-->
        <module>hotel-provider</module>
        <module>dubbo-provider</module>
        <!-- 主要放實體、接口、也可以放一些公用的工具類工程-->
        <module>api</module>
    </modules>

<!--    dependency依賴 版本號 的變量,也可以不要直接將版本號寫在version中-->
  <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <dubbo-spring-boot>1.0.0</dubbo-spring-boot>
      <dubbo.version>2.5.5</dubbo.version>
      <zkclient.version>0.10</zkclient.version>
      <lombok.version>1.16.18</lombok.version>
      <spring-boot.version>1.5.7.RELEASE</spring-boot.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
      <!--開啓web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 使用lombok實現JavaBean的get、set、toString、hashCode、equals等方法的自動生成  -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- Spring Boot Dubbo 依賴 -->
        <dependency>
            <groupId>com.alibaba.spring.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.0.0</version>
        </dependency>
        <!--zookeeper的客戶端依賴-->
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.11</version>
            <type>pom</type>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>UTF-8</encoding>
                </configuration>

            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

到這裏父工程配置結束

服務接口工程 api
1、pom寫法

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.hotels</groupId>
    <artifactId>api</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>api</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2、服務接口類

package com.hotel1.demo.api;

public interface DubboUserServer {
    String getUser(Integer id);
}

跟普通接口沒有兩樣,爲了簡單明瞭我這裏只有一個方法,如果用到實體類操作數據庫,可以創建實體類
無需其他過多配置,服務接口工程的配置結束

服務提供工程 dubbo-privoder
1、pom加入

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--子工程爲了繼承父工程的依賴,節省代碼,可以在parent標籤中加入父工程的jar包座標-->
    <parent>
        <groupId>com.hotels</groupId>
        <artifactId>dubbo-hotels</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <groupId>com.hotels</groupId>
    <artifactId>dubbo-privoder</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>dubbo-privoder</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
      <!--  爲了引入api服務接口來實現接口類,需要引入api工程的jar包  這樣可以引入api中的類-->
        <dependency>
            <groupId>com.hotels</groupId>
            <artifactId>api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

父工程的依賴可以被子工程引入,即子工程無需再寫一遍依賴,只需要parent父級依賴指定成子工程即可
dubbo-provider引入dubbo-hotels的pom,如圖
在這裏插入圖片描述
A工程想要引入B工程的類,需要以依賴的形式引入B類的jar,如圖
在這裏插入圖片描述

無論是dependency引入還是parent父級引入,關鍵在於要一一對應號groupId、artifactId、version等座標和版本,否則出錯

2、接口實現類

package com.provider.demo.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.hotel1.demo.api.DubboUserServer;  //此處的DubboUserServer正是引入了api工程的接口,dubbo-provider中並不需要寫此接口
import org.springframework.stereotype.Component;

//用到實體類對的話實體類要實現序列化接口
@Service(interfaceClass = DubboUserServer.class)//使用dubbo提供的service註解來暴露服務
@Component 
public class DubboUserServerImpl implements DubboUserServer {

    @Override
    public String getUser(Integer id) {
        String name = "";
        if(1==id){
            name = "董";
        }else if(2==id){
            name = "劉";
        }else{
            name = "楊";
        }
        return name;
    }

}

3、啓動類

package com.provider.demo;

import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubbo//添加此註解開啓dubbo容器  必要
public class DemoApplication {

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

}

4、properties.yml

server:
  port: 8083     //tomcat端口

dubbo:
  application:
     name: server-privoder  //應用程序名
  registry:
     address: zookeeper://127.0.0.1:2181?backup=127.0.0.1:2182,127.0.0.1:2183  //我這裏是zookeeper集羣的寫法
  protocol:
     name: dubbo
    #修改默認端口要寫成字符串形式,如果寫20880數字將無法識別,暴露的服務使用的是默認端口20880
     port: "20881"
  scan: com.provider.demo.impl   //用來掃描使用了dubbo暴露服務註解@Service的類所在的包

① 上面的文件其實就是類似 spring 的配置文件,而且,dubbo 底層就是 spring。

② 節點:dubbo:application
就是整個項目在分佈式架構中的唯一名稱,可以在 name 屬性中配置,另外還可以配置 owner 字段,表示屬於誰。
下面的參數是可以不配置的,這裏配置是因爲出現了端口的衝突,所以配置。

③ 節點:dubbo:monitor
監控中心配置, 用於配置連接監控中心相關信息,可以不配置,不是必須的參數。 本文就沒有配置

④ 節點:dubbo:registry
配置註冊中心的信息,比如,這裏我們可以配置 zookeeper 作爲我們的註冊中心。address 是註冊中心的地址,
也可以配置 N/A 表示由 dubbo 自動分配地址。或者說是一種直連的方式,不通過註冊中心。

⑤ 節點:dubbo:protocol
name:服務發佈的時候 dubbo 依賴什麼協議,可以配置 dubbo、webserovice、Thrift、Hessain、http等協議,用name來指定。
這裏僅解釋兩種協議:
dubbo:缺省協議是dubbo協議,採用單一長連接和 NIO 異步通訊,適合於小數據量大併發的服務調用,以及服務消費者機器數遠大於服務提供者機器數的情況。
hessian:Hessian底層採用Http通訊(同步),採用Servlet暴露服務。適用於傳入傳出參數數據包較大,消費者併發量少,提供者較多,可傳文件。

port:服務暴露的端口用port來指定,此處的端口數字必須用字符串表示,否則無法識別,會使用dubbo默認端口20880

⑥ 節點:dubbo:scan:
用來掃描使用了dubbo暴露服務註解@Service的類所在的包

服務消費工程 dubbo-customer
pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.hotels</groupId>
        <artifactId>dubbo-hotels</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <groupId>com.hotels</groupId>
    <artifactId>dubbo-customer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>dubbo-customer</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.hotels</groupId>
            <artifactId>api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

5、測試web類

package com.customer.demo.web;

import com.hotel1.demo.api.DubboUserServer;
import com.alibaba.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class TestController {

   
//引入服務接口的註解  關鍵地方
    @Reference
    DubboUserServer dubboUserServer;


    @RequestMapping(value = "/show", method = RequestMethod.GET)
    public String shows() {

        return dubboUserServer.getUser(2);
    }

}

6、啓動類同理加上@EnableDubbo

7、properties.yml

server:
  port: 8084

dubbo:
  application:
     name: server-customer
  registry:
    address: zookeeper://127.0.0.1:2181?backup=127.0.0.1:2182,127.0.0.1:2183
  protocol:
     name: dubbo
    #修改默認端口要寫成字符串形式
     port: "20880"
  scan: com.customer.demo.web   //掃描註解@Reference調用服務的類所在的包

啓動dubbo-customer,在瀏覽器地址欄輸入http://127.0.0.1:8084/test/show 即可測試

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