Spring Boot 2+Dubbo 學習系列2:搭建Spring Boot 2+Dubbo+Zookeeper集羣

本項目使用當前(2018年7月)最新的官方正式版本實踐,SpringBoot 2.0.3+dubbo-spring-boot-starter 0.2.0(即dubbo2.6.2)+zookeeper集羣

文章主要參考了Dubbo在Apache的項目主頁的文檔,還有Dubbo Spring Boot 工程在github的說明和例子

文章寫得較繁瑣,重點在後半部分

目錄:

一 項目結構

項目結構

項目名爲dubbo,其下分3個模塊base-interface,provider和consumer

  • base-interface:基礎接口模塊,對應的即Dubbo服務
  • provider:提供者
  • consumer:消費者

模塊功能

  • 相互關係
    主項目dubbo負責版本管理,provider和consumer都依賴base-interface接口,其中,provider提供了接口的具體實現,而consumer則調用了provider的實現,他們通過base-interface來確定使用規範(接口即契約)
  • 對應MVC關係
    對應到MVC的話,base-interface就是service(接口,爲提供實現),provider就相當於serviceImpl(service的實現類),而concumer就是controller的角色.
  • 框架依賴
    所以base-interface是單純的服務接口集,不需要額外的依賴,而provider只提供服務實現,並不對外開放,只需對內提供服務調用就好,不需要spring-web支持,真正對外開放接口的就只有consumer

二 項目搭建

新建dubbo項目,在dubbo項目下添加base-interface,provider和consumer 3個模塊
修改各個模塊pom文件,組成項目結構,具體如下

1 在主項目dubbo的pom引入子模塊並進行依賴的版本管理

注意,這裏的packing是pom,子模塊爲jar
而且,子模塊不定義groupId和version,即跟隨主項目的groupId和version
另外,這裏的插件是maven-deploy-plugin,並沒有spring-boot-maven-plugin,因爲一些子模塊不需要(如base-interface)

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.linshen.dubbo</groupId>
    <artifactId>dubbo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>dubbo</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>

    <!--引入的子模塊-->
    <modules>
        <module>base-interface</module>
        <module>provider</module>
        <module>consumer</module>
    </modules>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <dubbo-springboot.version>0.2.0</dubbo-springboot.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.boot</groupId>
                <artifactId>dubbo-spring-boot-starter</artifactId>
                <version>${dubbo-springboot.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba.boot</groupId>
                <artifactId>dubbo-spring-boot-actuator</artifactId>
                <version>${dubbo-springboot.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-deploy-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2 修改base-interface模塊如下

注意,這裏沒有引入spring-boot-maven-plugin插件,因爲base-interface並不是一個真正的SpringBoot項目,也沒有啓動類

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <artifactId>base-interface</artifactId>

    <name>base-interface</name>

    <parent>
        <groupId>com.linshen.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

</project>

3 在模塊provider和consumer引入依賴

注意這裏引入了actuator,非必須,也可以去掉的

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <artifactId>provider</artifactId>
    <packaging>jar</packaging>

    <name>provider</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>com.linshen.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <dependencies>
        <!-- 基礎接口模塊-->
        <dependency>
            <groupId>com.linshen.dubbo</groupId>
            <artifactId>base-interface</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-actuator</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

4 在consumer模塊中再引入web依賴

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

5 將base-interface的Application引導類刪除,其他無用的文件夾也刪去(如resource)

6 修改provider的Application引導類,使其按非web應用運行

@SpringBootApplication
public class ProviderApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(ProviderApplication.class)
                .web(WebApplicationType.NONE)
                .run(args);
    }
}

至此,項目搭建完畢

三 功能實現

按照前文講的,我們來實現最基礎的問候功能(hello和goodbye)

1 在base-interface模塊定義接口

如下,是一個很單純的接口

public interface HelloService {
    String sayHello(String name);
    String sayGoodbye(String name);
}

2 在provider模塊實現接口

如下,重點在於@Service註解

@Service(
        version = "${hello.service.version}",
        application = "${dubbo.application.id}",
        protocol = "${dubbo.protocol.id}",
        registry = "${dubbo.registry.id}"
)
public class DefaultHelloService implements HelloService {
    @Override
    public String sayHello(String name) {
        return "Hello "+name+" !";
    }

    @Override
    public String sayGoodbye(String name) {
        return "Goodbye "+name+" !";
    }

application.yml文件如下:
注意,dubbo.registry.address請設置爲真實zookeeper地址,我這裏用的是zookeeper集羣,具體可參考上一篇文章:SpringBoot2+Dubbo 學習系列1:使用Docker部署zookeeper
如果要簡單的話可以像官方教程一樣直接用廣播,這樣就不需要使用註冊中心了(相應的,就不能指定dubbo.registry.protocol)

dubbo.registry.id = my-registry
dubbo.registry.address = N/A

另外注意這裏給了dubbo.protocol的參數,因爲provider是要通過dubbo協議來提供服務的(當然也可以用其他協議,這裏不展開)

spring:
  application:
    name: linshen-dubbo-provider1
server:
  port: 9090
dubbo:
  registry:
    protocol: zookeeper
    address: ip:2181,ip:2182,ip:2183
    id: lin-registry-1
  protocol:
    port: 12345
    name: dubbo
    id: dubbo
    status: server
  application:
    name: linshen-dubbo-provider-name1
    id: linshen-dubbo-provider-id1
    qos-enable: true
    qos-port: 22222
  scan:
    basePackages: com.linshen.dubbo.provider.service
hello:
  service:
    version: 1.0.0

3 在consumer模塊編寫controller

如下,重點在於@Reference
注意,下面的註解中在官方給的例子中是把registry換成url,如url = “dubbo://localhost:12345”來指定dubbo服務地址,這樣下面yml文件就可以不用寫dubbo.registry板塊了(畢竟官方給的例子沒有真正的註冊中心),但我還是覺得使用一開始就使用zookeeper會更加自然,更容易理解

@RestController
public class HelloController {

    @Reference(
            version = "${hello.service.version}",
            application = "${dubbo.application.id}",
            registry = "${dubbo.registry.id}"
    )
    private HelloService helloService;

    @GetMapping("hello/{name}")
    public String sayHello(@PathVariable String name){
        return helloService.sayHello(name);
    }

    @GetMapping("goodbye/{name}")
    public String sayGoodbye(@PathVariable String name){
        return helloService.sayGoodbye(name);
    }
}

application.yml文件如下:
注意,這裏我開啓了actuator

spring:
  application:
    name: linshen-dubbo-consumer1
server:
  port: 9091
hello:
  service:
    version: 1.0.0
dubbo:
  application:
    id: linshen-dubbo-consumer-id1
    name: linshen-dubbo-consumer-name1
  registry:
    protocol: zookeeper
    address: ip:2181,ip:2182,ip:2183
    id: lin-registry-1
management:
  endpoint:
    dubbo-configs:
      enabled: true
    dubbo:
      enabled: true
    dubbo-services:
      enabled: true
    dubbo-properties:
      enabled: true
    dubbo-shutdown:
      enabled: true
    dubbo-references:
      enabled: true
  health:
    dubbo:
      status:
        defaults: memory
        extras: load,threadpool
  endpoints:
    web:
      exposure:
        include: '*'

至此項目搭建結束

四 項目啓動並測試

1 啓動項目

啓動provider,觀察日誌

這裏寫圖片描述
如圖是隻是日誌的一部分,其中紅線爲本機ip,藍線爲zookeeper所在主機ip,綠框爲連接建立狀態,從日誌中也可以看出來,大概流程是先初始化客戶端連接到zookeeper集羣,在開通一個socket連接到一臺zookeeper主機,,接着就註冊當前客戶端信息(包含dubbo協議地址,服務信息等等,如截圖),然後與註冊中心建立連接完成,會話建立,狀態更改爲CONNECTED,然後註冊中心會訂閱此provider信息並通知所有訂閱此provider信息的url.(這個流程只是從日誌上粗略地看的,並不一定準確)

啓動consumer,觀察日誌

前面和provider差不多,也是要把自身註冊到zookeeper上的,註冊完後還會多一些步驟,如下圖
這裏寫圖片描述
可以很直觀地看到,註冊完之後紅線比藍線要多得多,因爲註冊完之後就和zookeeper沒什麼事了,consumer從註冊中心獲得provider的信息後,便直接和provider建立連接,如圖中所示,是通過NettyClient建立的連接,然後從註冊中心查閱特定的dubbo service服務,然後建立引用關係

2 測試

使用PostMan測試如下(其實直接用鏈接打開就可以測試了…)

這裏寫圖片描述
這裏寫圖片描述

使用actuator查看如下

以簡單地查看dubbo信息爲例:
這裏寫圖片描述
dubbo還開放了很多其他的endpoint來監控
如dubbo/configs查看配置信息,dubbo/references查看引用實體等.
需要注意的是,由於使用的是SpringBoot2,所以Actuator的基礎路徑是ip:port/actuator,以前只是ip:port而已,這一點在dubbo的官方說明裏還沒有更改,詳情請看Spring Boot 2.0官方文檔之 Actuator

其他

到目前來看監控還是很不方便的,特別是當服務較多的時候,我們都值得Spring Cloud的服務治理中心是有終端網頁的,圖形化界面,關係看起來非常直觀,舒服,當然Dubbo也有,而且還原生支持中文,那就是Dubbo Admin,只不過它得另外部署,界面如下,部署放在下一篇文章說:Spring Boot 2+Dubbo 學習系列3:dubbo-ops 之 Dubbo Admin
這裏寫圖片描述
這裏寫圖片描述

文章參考:
http://dubbo.apache.org
http://start.dubbo.io/
https://github.com/apache/incubator-dubbo-spring-boot-project/blob/master/README_CN.md
Spring Boot 2+Dubbo 學習系列1:使用Docker部署zookeeper
Spring Boot 2+Dubbo 學習系列2:搭建Spring Boot 2+Dubbo+Zookeeper集羣
Spring Boot 2+Dubbo 學習系列3:dubbo-ops 之 Dubbo Admin

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