一步一步搭建 springboot-2.1.3+dubbo-2.7.1 專案

姐夫發表於2019-03-23

寫在前面

作為一個php程式設計師轉java開發,一直停留在 hello world 的水平上,最近由於一時發熱想試一下 dubbo 的新版本,但是 github 找了一遍又一遍都沒有看到有demo,而官方給出的例子複製出來是沒辦法單獨執行的,不是這個錯就那個錯,反正搞了一下午也沒有解決。

於是決定自己試一試,填補一下搜尋引擎空白。

開發環境

  • Spring Boot: 2.1.3.RELEASE
  • Dubbo: 2.7.1-SNAPSHOT
  • 開發工具:Mac IDEA

實戰

廢話少說,show me the code !

建立專案

現在開始用 IDEA 建立一個沒有程式碼的 Spring boot maven 工程

一步一步搭建 springboot-2.1.3+dubbo-2.7.1 專案

選擇 Spring Initializr 初始化專案

一步一步搭建 springboot-2.1.3+dubbo-2.7.1 專案

一步一步搭建 springboot-2.1.3+dubbo-2.7.1 專案

一步一步搭建 springboot-2.1.3+dubbo-2.7.1 專案

建立模組

建立 api 模組,即 interface 定義

一步一步搭建 springboot-2.1.3+dubbo-2.7.1 專案

建立 service 模組,即 provider 服務提供者

一步一步搭建 springboot-2.1.3+dubbo-2.7.1 專案

建立 web 模組,即 consumer 服務消費者

一步一步搭建 springboot-2.1.3+dubbo-2.7.1 專案

建立完這個模組之後來執行個 mvn clean install 試一下,結果報錯了

[INFO] skip non existing resourceDirectory /Users/jeftom/workspace/java/dubbo-sample/dubbo-demo/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ dubbo-demo ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ dubbo-demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/jeftom/workspace/java/dubbo-sample/dubbo-demo/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ dubbo-demo ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ dubbo-demo ---
[INFO] No tests to run.
[INFO] 
[INFO] --- maven-jar-plugin:3.1.1:jar (default-jar) @ dubbo-demo ---
[WARNING] JAR will be empty - no content was marked for inclusion!
[INFO] Building jar: /Users/jeftom/workspace/java/dubbo-sample/dubbo-demo/target/dubbo-demo-0.0.1-SNAPSHOT.jar
[INFO] 
[INFO] --- spring-boot-maven-plugin:2.1.3.RELEASE:repackage (repackage) @ dubbo-demo ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.142 s
[INFO] Finished at: 2019-03-23T22:05:17+08:00
[INFO] Final Memory: 24M/395M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.3.RELEASE:repackage (repackage) on project dubbo-demo: Execution repackage of goal org.springframework.boot:spring-boot-maven-plugin:2.1.3.RELEASE:repackage failed: Unable to find main class -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginExecutionException
複製程式碼

一步一步搭建 springboot-2.1.3+dubbo-2.7.1 專案

找到 Tests 單元測試用例,加上 @Ignore 註釋跳轉先,剩下的先不管那麼多了。

主模組配置

在根模組的 pom.xml 裡增加

<packaging>pom</packaging>

<modules>
    <module>dubbo-demo-api</module>
    <module>dubbo-demo-service</module>
    <module>dubbo-demo-web</module>
</modules>
複製程式碼

打包外掛也需要調整一下,因為根模板沒有使用到 spring boot 的 main 啟動類,換成 maven 的打包外掛才能繼續下去。

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <version>3.1.0</version>
            </plugin>
            <plugin>
                <artifactId>maven-site-plugin</artifactId>
                <version>3.7.1</version>
            </plugin>
            <plugin>
                <artifactId>maven-project-info-reports-plugin</artifactId>
                <version>3.0.0</version>
            </plugin>
        </plugins>
    </pluginManagement>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-site-plugin</artifactId>
            <configuration>
                <locales>en,fr</locales>
            </configuration>
        </plugin>
    </plugins>

    <!-- 這裡要把 spring boot 自帶的 spring-boot-maven-plugin 外掛換成 maven-site-plugin,否則 mvn 打包會報錯 -->
    <!-- <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins> -->
</build>
複製程式碼

在其它三個子模組的 pom.xml 增加

<packaging>jar</packaging>
複製程式碼

修改完成之後,執行 mvn clean install 試一下

[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] dubbo-demo-api ..................................... SUCCESS [  5.428 s]
[INFO] dubbo-demo-service ................................. SUCCESS [  1.299 s]
[INFO] dubbo-demo-web ..................................... SUCCESS [  3.195 s]
[INFO] dubbo-demo ......................................... SUCCESS [  0.039 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11.258 s
[INFO] Finished at: 2019-03-23T22:21:46+08:00
[INFO] Final Memory: 50M/525M
[INFO] ------------------------------------------------------------------------
複製程式碼

離成功又近了一步,雖然還沒有任何程式碼,但是起碼幾個模組已經 build 通過了。

dubbo-demo-api 模組

刪除 dubbo-demo-api 裡的啟動類,因為這個模組主要儲存的是介面的定義。

一步一步搭建 springboot-2.1.3+dubbo-2.7.1 專案

增加 DemoApi 介面類

package com.example.dubbo.demo.api;

/**
 * Demo 介面定義
 *
 * @author jeftom
 * @date 2019-03-23 22:35
 * @since 1.0.0
 */
public interface DemoApi {
   String sayHello(String name);
}
複製程式碼

pom 檔案打包外掛改為:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
        </plugin>
    </plugins>
</build>
複製程式碼

dubbo-demo-service 模組

這個模組主要的功能是介面的實現,業務功能的服務提供者。

一步一步搭建 springboot-2.1.3+dubbo-2.7.1 專案

先來看看該模組的 pom.xml 配置:

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example.dubbo</groupId>
    <artifactId>dubbo-demo-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>dubbo-demo-service</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- dubbo provider 啟動不成功的主要問題在這裡,沒有新增 spring-boot-starter-web 依賴,所以啟動日誌裡一直沒有顯示 “o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8087 (http)” 這行日誌輸出 -->
        <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>

        <!-- 這個是定義的介面包,在 provider 和 consumer 都需要引用的 -->
        <dependency>
            <groupId>com.example.dubbo</groupId>
            <artifactId>dubbo-demo-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <!-- 新增 dubbo 依賴 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.7.1-SNAPSHOT</version>
            <exclusions>
                <exclusion>
                    <artifactId>spring</artifactId>
                    <groupId>org.springframework</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.10</version>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-log4j12</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.0.1</version>
        </dependency>
    </dependencies>

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

</project>
複製程式碼

重點要說這裡,因為建立模組的時候沒有勾選 web 依賴,所以 pom 裡只有 spring-boot-starter,並沒包含 spring-boot-starter-web 的依賴,啟動服務的時候總是完成之後就退出掉,mvn install 也是正常的,百思不得其姐,這裡花費了我幾個小時的時間。增加完 spring-boot-starter-web 依賴之後,啟動日誌裡就能看到 tomcat 的日誌了

o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8087 (http)
複製程式碼

現在我們來建立一個 DemoApiImpl 類,對 sayHello 方法實現響應:

一步一步搭建 springboot-2.1.3+dubbo-2.7.1 專案

package com.example.dubbo.demo.service.impl;

import com.example.dubbo.demo.api.DemoApi;
import org.apache.dubbo.config.annotation.Service;

/**
 * demo 實現類
 *
 * @author jeftom
 * @date 2019-03-23 23:04
 * @since 1.0.0
 */
@Service
public class DemoApiImpl implements DemoApi {
   /**
    * 實現 sayHello 介面
    *
    * @param name
    * @return
    */
   @Override
   public String sayHello(String name) {
      return "Hello, " + name + " (from Spring Boot with dubbo-2.7.1)";
   }
}
複製程式碼

DubboDemoServiceApplication 啟動類需要增加 dubbo 配置註解:

package com.example.dubbo.demo.service;

import org.apache.dubbo.config.spring.context.annotation.DubboComponentScan;
import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 增加了 EnableDubboConfig 和 DubboComponentScan 的註解,啟動時自動掃描
 *
 */
@EnableDubboConfig
@DubboComponentScan("com.example.dubbo.demo.service.impl")
@SpringBootApplication
public class DubboDemoServiceApplication {

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

}
複製程式碼

增加 dubbo 配置檔案:

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

    <!-- 定義了提供方應用資訊,用於計算依賴關係;在 dubbo-admin 或 dubbo-monitor 會顯示這個名字 -->
    <dubbo:application name="${dubbo.application.name}" owner="jeftom" organization="jeftom"  />

    <!-- 使用 zookeeper 註冊中心暴露服務,注意要先開啟 zookeeper-->
    <dubbo:registry id="zookeeper-registry" protocol="${dubbo.registry.protocol}" address="${dubbo.registry.address}" />

    <!-- dubbo協議在20880埠暴露服務 -->
    <dubbo:protocol name="${dubbo.protocol.name}" port="${dubbo.protocol.port}" accesslog="dubbo-access.log"/>
    <dubbo:provider retries="0" timeout="30000"/>
    <dubbo:monitor protocol="registry"/>

    <!-- 使用 dubbo 協議實現定義好的 Service Api 介面-->
    <dubbo:service interface="com.example.dubbo.demo.api.DemoApi" ref="DemoApiImpl" retries="0" timeout="60000" />
</beans>
複製程式碼

spring 專案的 application.properties 配置檔案:

spring.config.name=application

# spring 的環境配置
spring.profiles.active=dev
# 服務啟動埠,即內建 tomcat 啟動時佔用的埠
server.port=8087

#dubbo config
#應用定義了提供方應用資訊,用於計算依賴關係;在 dubbo-admin 或 dubbo-monitor 會顯示這個名字,方便辨識
dubbo.application.name=dubbo-demo-service
#應用所屬者
dubbo.application.owner=jeftom
#應用所屬組織
dubbo.application.organization=jeftom

# 使用 zookeeper 註冊中心暴露服務,注意要先開啟 zookeeper
# 註冊中心id
dubbo.registry.id=zookeeper-registry
# 註冊中心協議
dubbo.registry.protocol=zookeeper
# 註冊中心地址
dubbo.registry.address=zookeeper.tencus.com:2181

# dubbo協議在20880埠暴露服務
# 協議名稱
dubbo.protocol.name=dubbo
# 協議埠
dubbo.protocol.port=20880
# 協議訪問log
dubbo.protocol.accesslog=dubbo-access.log
# 重試次數
dubbo.provider.retries=0
# 超時時間
dubbo.provider.timeout=3000
# 註冊監控中心
dubbo.monitor.protocol=registry
複製程式碼

至此,我們的服務提供者已經可以正常啟動了,通過 dubbo-admin 可以看到服務已經註冊到 zookeeper 裡。

dubbo-demo-web 模組

這個模組是 dubbo 的 consumer 服務,用於消費提供者提供的服務,服務啟動後會與提供者進行連線,完成服務呼叫。

一步一步搭建 springboot-2.1.3+dubbo-2.7.1 專案

pom.xml 配置檔案:

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example.dubbo</groupId>
    <artifactId>dubbo-demo-web</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>dubbo-demo-web</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

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

        <!-- dubbo provider 啟動不成功的主要問題在這裡,沒有新增 spring-boot-starter-web 依賴,所以啟動日誌裡一直沒有顯示 “o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8087 (http)” 這行日誌輸出 -->
        <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>

        <!-- 這個是定義的介面包,在 provider 和 consumer 都需要引用的 -->
        <dependency>
            <groupId>com.example.dubbo</groupId>
            <artifactId>dubbo-demo-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <!-- 新增 dubbo 依賴 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.7.1-SNAPSHOT</version>
            <exclusions>
                <exclusion>
                    <artifactId>spring</artifactId>
                    <groupId>org.springframework</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.10</version>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-log4j12</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.0.1</version>
        </dependency>
    </dependencies>

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

</project>
複製程式碼

spring 應用的 application.properties 配置:

spring.config.name=application

# spring 的環境配置
spring.profiles.active=dev
# 服務啟動埠,即內建 tomcat 啟動時佔用的埠
server.port=8088

# Qos 運維監控
dubbo.application.qosEnable=true
dubbo.application.qosPort=33333
dubbo.application.qosAcceptForeignIp=false

# dubbo config
# 應用定義了提供方應用資訊,用於計算依賴關係;在 dubbo-admin 或 dubbo-monitor 會顯示這個名字,方便辨識
dubbo.application.name=dubbo-demo-service
# 應用所屬者
dubbo.application.owner=jeftom
# 應用所屬組織
dubbo.application.organization=jeftom

# 使用 zookeeper 註冊中心暴露服務,注意要先開啟 zookeeper
# 註冊中心id
dubbo.registry.id=zookeeper-registry
# 註冊中心協議
dubbo.registry.protocol=zookeeper
# 註冊中心地址
dubbo.registry.address=zookeeper.tencus.com:2181

# dubbo協議在20880埠暴露服務
# 協議名稱
dubbo.protocol.name=dubbo
# 協議埠
dubbo.protocol.port=20880
# 協議訪問log
dubbo.protocol.accesslog=dubbo-access.log
# 重試次數
dubbo.provider.retries=0
# 超時時間
dubbo.provider.timeout=3000
# 註冊監控中心
dubbo.monitor.protocol=registry
複製程式碼

如果同一臺機器上同時啟動兩個服務,會導致 Qos 埠衝突:

main [server.Server] 102 [ERROR]  [DUBBO] qos-server can not bind localhost:22222
複製程式碼

DubboDemoWebApplication 消費者的啟動類增加以下兩行註解:

@EnableDubboConfig
@DubboComponentScan("com.example.dubbo.demo.web.service")
複製程式碼

分別建立 DemoService 服務類和 DemoController 控制器,

DemoService.java 類

package com.example.dubbo.demo.web.service;

import com.example.dubbo.demo.api.DemoApi;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * 消費者服務層
 *
 * @author jeftom
 * @date 2019-03-24 00:49
 * @since 1.0.0
 */
@Service
public class DemoService {
   private static final Logger LOGGER = LoggerFactory.getLogger(DemoService.class);

   @Reference
   private DemoApi demoApi;

   public String sayHello(String name) {
      return demoApi.sayHello(name);
   }
}
複製程式碼

DemoController.java 控制器類

package com.example.dubbo.demo.web.controller;

import com.example.dubbo.demo.web.service.DemoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * demo 控制器
 *
 * @author jeftom
 * @date 2019-03-24 00:51
 * @since 1.0.0
 */
@RestController
@RequestMapping("/demo")
public class DemoController {
   private static Logger logger = LoggerFactory.getLogger(DemoController.class);

   @Autowired
   private DemoService demoService;

   /**
    * 測試方法,瀏覽器訪問 /demo/index 可以看到響應結果了
    *
    * @return
    */
   @RequestMapping(value = "/index", method = RequestMethod.GET)
   @ResponseBody
   public String index() {
      return demoService.sayHello("dubbo");
   }
}
複製程式碼

好了,現在可以重新 reimport 和 mvn install 一下看看有沒有報錯,如果沒有報了,啟動 service 和 web 兩個服務,然後開啟瀏覽器訪問,擼了這麼久,終於出來了。

一步一步搭建 springboot-2.1.3+dubbo-2.7.1 專案

結語

以上是是我花了兩天才除錯通的 dubbo-2.7.1 版本呼叫服務的demo,如果你也正準備使用 dubbo 嘗試新版本來做服務化開發,希望本文對你有一點點的幫助,非常感謝** 阿里團隊**開源出來這麼優秀的RPC解決方案。

相關文章