3 - 使用 Dubbo x Spring Boot 開發微服務應用程式
目標
從零開始基於 Dubbo x Spring Boot 開發微服務,並了解 Dubbo x Spring Boot 的設定方法。
難度
低
環境需求
系統:Windows、Linux、MacOS
JDK 8 及以上版本(建議使用 JDK 17)
Git
IntelliJ IDEA(可選)
Docker(可選)
專案介紹
在此任務中,將分為三個子模組獨立開發,模擬生產環境中的部署架構。
.//apache/dubbo-samples/1-basic/dubbo-samples-spring-boot
├── dubbo-samples-spring-boot-interface // shared API module
├── dubbo-samples-spring-boot-consumer // consumer module
└── dubbo-samples-spring-boot-provider // server module
如上圖所示,共有 3 個模組,其中 interface
模組被 consumer
和 provider
模組共同依賴,存放 RPC 通訊使用的 API 介面。
.//apache/dubbo-samples/1-basic/dubbo-samples-spring-boot
├── dubbo-samples-spring-boot-interface // shared API module
│ ├── pom.xml
│ └── src
│ └── main
│ └── java
│ └── org
│ └── apache
│ └── dubbo
│ └── springboot
│ └── demo
│ └── DemoService.java // API interface
├── dubbo-samples-spring-boot-consumer // consumer module
│ ├── pom.xml
│ └── src
│ ├── main
│ │ ├── java
│ │ │ └── org
│ │ │ └── apache
│ │ │ └── dubbo
│ │ │ └── springboot
│ │ │ └── demo
│ │ │ └── consumer
│ │ │ ├── ConsumerApplication.java // consumer startup class
│ │ │ └── Task.java // The consumer simulates calling tasks
│ │ └── resources
│ │ └── application.yml // Spring Boot configuration file
├── dubbo-samples-spring-boot-provider // server module
│ ├── pom.xml
│ └── src
│ └── main
│ ├── java
│ │ └── org
│ │ └── apache
│ │ └── dubbo
│ │ └── springboot
│ │ └── demo
│ │ └── provider
│ │ ├── DemoServiceImpl.java // server implementation class
│ │ └── ProviderApplication.java // server startup class
│ └── resources
│ └── application.yml // Spring Boot configuration file
└── pom.xml
以上是本教學會用到的專案檔案結構。
快速部署(直接基於 Samples 啟動)
本章節將逐步教您如何透過幾個簡單的指令部署並執行基於 Dubbo x Spring Boot 的使用案例。
注意:本章節部署的程式碼細節可以在 apache/dubbo-samples 倉庫中的 1-basic/dubbo-samples-spring-boot
找到,下一章節也會進行說明。
1. 取得測試專案
在開始整個教學之前,我們需要取得測試專案的程式碼。所有 Dubbo 的測試案例程式碼都儲存在 apache/dubbo-samples 這個儲存庫中,以下指令可以協助您取得 Samples 儲存庫中的所有程式碼。
git clone --depth=1 --branch master git@github.com:apache/dubbo-samples.git
2. 啟動一個簡單的註冊中心
對於一個微服務應用程式來說,註冊中心是一個不可或缺的組件。只有透過註冊中心,消費者才能成功地發現伺服器的地址資訊,進而發起呼叫。
為了讓本教學更容易上手,我們提供了一個基於 Apache Zookeeper 註冊中心的簡易啟動器。如果您需要在生產環境中部署註冊中心,請參考 生產環境初始化 來部署一個高可用的註冊中心。
Windows:
./mvnw.cmd clean compile exec:java -pl tools/embedded-zookeeper
Linux / MacOS:
./mvnw clean compile exec:java -pl tools/embedded-zookeeper
Docker:
docker run --name some-zookeeper -p 2181:2181 --restart always -d zookeeper
3. 本地打包 API 模組
為了成功編譯伺服器和消費者模組,您需要先在本機打包並安裝 dubbo-samples-spring-boot-interface
模組。
./mvnw clean install -pl 1-basic/dubbo-samples-spring-boot
./mvnw clean install -pl 1-basic/dubbo-samples-spring-boot/dubbo-samples-spring-boot-interface
4. 啟動服務提供者
啟動註冊中心後,下一步是啟動一個對外提供服務的服務提供者。dubbo-samples 中也提供了對應的範例,可透過以下指令快速拉起。
Windows:
./mvnw.cmd clean compile exec:java -pl 1-basic/dubbo-samples-spring-boot/dubbo-samples-spring-boot-provider "-Dexec.mainClass=org.apache.dubbo.springboot.demo.provider.ProviderApplication"
Linux / MacOS:
./mvnw clean compile exec:java -pl 1-basic/dubbo-samples-spring-boot/dubbo-samples-spring-boot-provider -Dexec.mainClass="org.apache.dubbo.springboot.demo.provider.ProviderApplication"
Note: You need to open an independent terminal to run, and the command will keep executing.
執行上述指令後,稍等片刻,待出現以下日誌(Current Spring Boot Application is await
),即表示服務提供者已啟動,表示服務提供者可以對外提供服務。
2023-02-08 17:13:00.357 INFO 80600 --- [lication.main()] o.a.d.c.d.DefaultApplicationDeployer : [DUBBO] Dubbo Application[1.1](dubbo-springboot-demo-provider) is ready., dubbo version: 3.2 .0-beta.4, current host: 30.221.128.96
2023-02-08 17:13:00.369 INFO 80600 --- [lication.main()] o.a.d.s.d.provider.ProviderApplication : Started ProviderApplication in 9.114 seconds (JVM running for 26.522)
2023-02-08 17:13:00.387 INFO 80600 --- [pool-1-thread-1].b.c.e.AwaitingNonWebApplicationListener : [Dubbo] Current Spring Boot Application is await...
5. 啟動服務消費者
最後一步是啟動一個服務消費者來呼叫服務提供者,這是 RPC 呼叫的核心,為服務消費者呼叫服務提供者提供了橋樑。
Windows:
./mvnw.cmd clean compile exec:java -pl 1-basic/dubbo-samples-spring-boot/dubbo-samples-spring-boot-consumer "-Dexec.mainClass=org.apache.dubbo.springboot.demo.consumer.ConsumerApplication"
Linux / MacOS:
./mvnw clean compile exec:java -pl 1-basic/dubbo-samples-spring-boot/dubbo-samples-spring-boot-consumer -Dexec.mainClass="org.apache.dubbo.springboot.demo.consumer.ConsumerApplication"
執行上述指令後,稍等片刻,待出現以下日誌(Hello world
)。印出的資料是經過服務提供者處理後返回的,標誌著一次服務呼叫的成功。
2023-02-08 17:14:33.045 INFO 80740 --- [lication.main()] o.a.d.s.d.consumer.ConsumerApplication : Started ConsumerApplication in 11.052 seconds (JVM running for 31.62)
Receive result ======> Hello world
2023-02-08 17:14:33.146 INFO 80740 --- [pool-1-thread-1].b.c.e.AwaitingNonWebApplicationListener : [Dubbo] Current Spring Boot Application is await...
Wed Feb 08 17:14:34 CST 2023 Receive result ======> Hello world
Wed Feb 08 17:14:35 CST 2023 Receive result ======> Hello world
Wed Feb 08 17:14:36 CST 2023 Receive result ======> Hello world
Wed Feb 08 17:14:37 CST 2023 Receive result ======> Hello world
動手實作 (從零程式碼開發版本)
本章將透過循序漸進的教學,教您如何從零開始開發一個微服務應用程式。
1. 啟動註冊中心
對於一個微服務應用程式來說,註冊中心是一個不可或缺的組件。只有透過註冊中心,消費者才能成功地發現伺服器的地址資訊,進而發起呼叫。
為了讓本教學更容易上手,我們提供了一個基於 Apache Zookeeper 註冊中心的簡易啟動器。如果您需要在生產環境中部署註冊中心,請參考 生產環境初始化 來部署一個高可用的註冊中心。
Windows:
git clone --depth=1 --branch master git@github.com:apache/dubbo-samples.git
cd dubbo-samples
./mvnw.cmd clean compile exec:java -pl tools/embedded-zookeeper
Linux / MacOS:
git clone --depth=1 --branch master git@github.com:apache/dubbo-samples.git
cd dubbo-samples
./mvnw clean compile exec:java -pl tools/embedded-zookeeper
Docker:
docker run --name some-zookeeper -p 2181:2181 --restart always -d zookeeper
2. 初始化專案
從本節開始,將基於 IntelliJ IDEA 建置和測試專案。
如上圖所示,即可建置一個基礎專案。
建置基礎專案後,我們需要建立三個子模組 dubbo-spring-boot-demo-interface
、dubbo-spring-boot-demo-provider
和 dubbo-spring-boot-demo-consumer
。
建立完三個子模組後,您需要建立以下資料夾
在
dubbo-spring-boot-demo-consumer/src/main/java
下建立org.apache.dubbo.springboot.demo.consumer
套件在
dubbo-spring-boot-demo-interface/src/main/java
下建立org.apache.dubbo.springboot.demo
套件在
dubbo-spring-boot-demo-provider/src/main/java
下建立org.apache.dubbo.springboot.demo.provider
套件
最終的資料夾參考如上圖所示。
3. 加入 Maven dependencies (相依性)
初始化專案後,我們需要先加入 Dubbo 相關的 maven 相依性。
對於多模組專案,首先需要在父專案的 pom.xml
中設定相依性資訊。
編輯 ./pom.xml
檔案,並加入以下設定。
<properties>
<dubbo.version>3.2.0-beta.4</dubbo.version>
<spring-boot.version>2.7.8</spring-boot.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-bom</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugin Management>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
接著在 dubbo-spring-boot-consumer
和 dubbo-spring-boot-provider
兩個模組的 pom.xml
中設定具體的相依性。
編輯 ./dubbo-spring-boot-consumer/pom.xml
和 ./dubbo-spring-boot-provider/pom.xml
,並加入以下設定。
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-samples-spring-boot-interface</artifactId>
<version>${project.parent.version}</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
<type>pom</type>
<exclusions>
<exclusion>
<artifactId>slf4j-reload4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- spring boot starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
在此設定中,定義了 dubbo 和 zookeeper(以及對應的連接器 curator)的相依性。
加入上述設定後,您可以透過 IDEA 的 Maven - Reload All Maven Projects
重新整理相依性。
4. 定義服務介面
服務介面是 Dubbo 中消費者和伺服器之間的橋樑。
在 dubbo-spring-boot-demo-interface
模組的 org.apache.dubbo.samples.api
下建立 DemoService
介面,定義如下
package org.apache.dubbo.springboot.demo;
public interface DemoService {
String sayHello(String name);
}
在 DemoService
中,定義了 sayHello
方法。後續服務端發佈的服務以及消費端訂閱的服務都是圍繞 DemoService
介面展開的。
5. 定義服務端的實現
定義好服務介面後,就可以在服務端定義對應的實現了。與消費端相比,這部分的實現是遠端實現,本地沒有相關資訊。
在 dubbo-spring-boot-demo-provider
模組的 org.apache.dubbo.samples.provider
下建立 DemoServiceImpl
類別,定義如下
package org.apache.dubbo.springboot.demo.provider;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.springboot.demo.DemoService;
@DubboService
public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
return "Hello " + name;
}
}
在 DemoServiceImpl
中,實現 DemoService
介面,為 sayHello
方法返回 Hello name
。
注意:在 DemoServiceImpl
類別上添加了 @DubboService
註解。通過此配置,即可基於 Spring Boot 發佈 Dubbo 服務。
6. 配置服務端 Yaml 配置檔
從這一步驟到步驟 7,將通過 Spring Boot 配置 Dubbo 的一些基本資訊。
首先,我們先來建立服務端的配置檔。
在 dubbo-spring-boot-demo-provider
模組的 resources
資源資料夾下建立 application.yml
檔案,定義如下
dubbo:
application:
name: dubbo-springboot-demo-provider
protocol:
name: dubbo
port: -1
registry:
address: zookeeper://${zookeeper.address:127.0.0.1}:2181
在這個配置檔中,定義了 Dubbo 應用名稱、Dubbo 協定資訊以及 Dubbo 使用的註冊中心地址。
7. 配置消費端 Yaml 配置檔
同樣地,我們需要為消費端建立一個配置檔。
在 dubbo-spring-boot-demo-consumer
模組的 resources
資源資料夾下建立 application.yml
檔案,定義如下
dubbo:
application:
name: dubbo-springboot-demo-consumer
protocol:
name: dubbo
port: -1
registry:
address: zookeeper://${zookeeper.address:127.0.0.1}:2181
在這個配置檔中,定義了 Dubbo 應用名稱、Dubbo 協定資訊以及 Dubbo 使用的註冊中心地址。
8. 基於 Spring 配置服務端啟動類別
除了配置 Yaml 配置檔外,我們還需要建立一個基於 Spring Boot 的啟動類別。
首先,我們先建立服務端的啟動類別。
在 dubbo-spring-boot-demo-provider
模組的 org.apache.dubbo.springboot.demo.provider
下建立 Application
類別,定義如下
package org.apache.dubbo.springboot.demo.provider;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
在這個啟動類別中,配置了一個 ProviderApplication
,用於讀取上面步驟 6 中定義的 application.yml
配置檔並啟動應用程式。
9. 基於 Spring 配置消費端啟動類別
同樣地,我們需要為消費端建立一個啟動類別。
在 dubbo-spring-boot-demo-consumer
模組的 org.apache.dubbo.springboot.demo.consumer
下建立 Application
類別,定義如下
package org.apache.dubbo.springboot.demo.consumer;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
在這個啟動類別中,配置了一個 ConsumerApplication
,用於讀取上面步驟 7 中定義的 application.yml
配置檔並啟動應用程式。
10. 配置消費端請求任務
除了配置消費端的啟動類別外,我們還可以在 Spring Boot 模式下基於 CommandLineRunner
建立
在 dubbo-spring-boot-demo-consumer
模組的 org.apache.dubbo.springboot.demo.consumer
下建立一個 Task
類別,定義如下
package org.apache.dubbo.springboot.demo.consumer;
import java.util.Date;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.springboot.demo.DemoService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class Task implements CommandLineRunner {
@DubboReference
private DemoService demoService;
@Override
public void run(String... args) throws Exception {
String result = demoService. sayHello("world");
System.out.println("Receive result ======> " + result);
new Thread(()-> {
while (true) {
try {
Thread. sleep(1000);
System.out.println(new Date() + " Receive result ======> " + demoService.sayHello("world"));
} catch (InterruptedException e) {
e.printStackTrace();
Thread. currentThread(). interrupt();
}
}
}).start();
}
}
在 Task
類別中,通過 @DubboReference
從 Dubbo 獲取一個 RPC 訂閱,這個 demoService
可以像本地呼叫一樣直接呼叫。在 run
方法中為呼叫建立了一個執行緒。
11. 啟動應用程式
截至步驟 10,程式碼已經開發完成,本節將啟動整個專案並進行驗證。
首先是啟動 org.apache.dubbo.samples.provider.Application
,稍等片刻出現如下圖所示的日誌 (Current Spring Boot Application is await
),表示服務提供者已啟動,標誌著服務提供者可以對外提供服務。
[Dubbo] Current Spring Boot Application is await...
然後啟動 org.apache.dubbo.samples.client.Application
,稍等片刻可以看到如下圖所示的日誌 (Hello world
),表示服務消費者已啟動,並且成功獲取到對服務端的呼叫。
Receive result ======> Hello world
延伸閱讀
1. Dubbo 的 Spring 配置介紹
Dubbo 的主要配置方式包括 yaml 配置內容、@DubboReference
和 @DubboService
等。更多細節,請參考[註解配置 | Apache Dubbo](/zh-cn/overview/mannual/java-sdk/reference-manual /config/annotation/) 文章。
更多
本教學介紹如何基於 Dubbo x Spring Boot 開發微服務應用程式。下一節將介紹另一種 Dubbo 配置方法 - Dubbo x Spring XML。