寫在前面
作為一個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 工程
選擇 Spring Initializr 初始化專案
建立模組
建立 api 模組,即 interface 定義
建立 service 模組,即 provider 服務提供者
建立 web 模組,即 consumer 服務消費者
建立完這個模組之後來執行個 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
複製程式碼
找到 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 裡的啟動類,因為這個模組主要儲存的是介面的定義。
增加 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 模組
這個模組主要的功能是介面的實現,業務功能的服務提供者。
先來看看該模組的 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 方法實現響應:
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 服務,用於消費提供者提供的服務,服務啟動後會與提供者進行連線,完成服務呼叫。
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 兩個服務,然後開啟瀏覽器訪問,擼了這麼久,終於出來了。
結語
以上是是我花了兩天才除錯通的 dubbo-2.7.1 版本呼叫服務的demo,如果你也正準備使用 dubbo 嘗試新版本來做服務化開發,希望本文對你有一點點的幫助,非常感謝** 阿里團隊**開源出來這麼優秀的RPC解決方案。
- 附 demo 原始碼下載:github.com/jeftom/dubb…