1 - 快速部署微服務應用程式
背景
作為一個微服務框架,Dubbo 最重要的是為使用者提供跨進程 RPC 遠端呼叫能力。如上圖所示,Dubbo 的服務消費者 (Consumer) 通過一系列任務向服務提供者 (Provider) 發送請求。
為了實現這樣的目標,Dubbo 引入了註冊中心元件。通過註冊中心,服務消費者可以感知服務提供者的連接方式,從而將請求發送到正確的服務提供者。
目標
了解微服務的呼叫方式和 Dubbo 的能力
難度
低
環境需求
系統:Windows、Linux、MacOS
JDK 8 及以上版本(建議使用 JDK17)
Git
Docker(可選)
實作
本章將逐步教您如何通過幾個簡單的命令部署和運行最簡單的 Dubbo 用例。
1. 取得測試專案
在開始整個教學之前,我們需要取得測試專案的程式碼。Dubbo 的所有測試用例程式碼都存儲在 apache/dubbo-samples 倉庫中,以下命令可以幫助您取得 Samples 倉庫中的所有程式碼。
git clone --depth=1 --branch master git@github.com:apache/dubbo-samples.git
2. 了解 Dubbo Samples 的專案結構
在本地複製 apache/dubbo-samples 倉庫後,本節將說明倉庫的具體組織。
.
├── codestyle // style configuration file for development
├── 1-basic // basic introductory use cases
├── 2-advanced // advanced usage
├── 3-extensions // Example of extension usage
├── 4-governance // service governance use cases
├── 10-task // Example of Dubbo learning series
├── 99-integration // integration test use
├── test // integration test use
└── tools // three-party component quick start tool
如上表所示,apache/dubbo-samples 主要包含三部分:程式碼風格檔案、測試程式碼和整合測試。
程式碼風格檔案可在開發 Dubbo 程式碼時使用,包含 IntelliJ IDEA 的設定檔。
測試程式碼是本教材所需的重點內容,目前包含 5 個部分:供入門者使用的基礎入門用例、供開發者使用的高階進階用法、供中介軟體維護者使用的擴充 Dubbo 周邊擴充套件使用範例、供生產環境使用的服務治理用例,以及 Dubbo 學習系列。本文將基於基礎入門用例,講解使用 Dubbo API 最簡單的方式。
整合測試是 Dubbo 品質保證體系的重要組成部分,每個版本的 Dubbo 都會對所有範例進行回歸驗證,確保 Dubbo 的所有變更都不會影響範例的使用。
3. 啟動一個簡易的註冊中心
從本節開始,將透過三個指令正式部署一個微服務應用程式。
從背景一節中,我們可以看到運行 Dubbo 應用程式的一個主要前提是部署一個註冊中心。為了讓本教學更容易使用,我們提供了一個基於 Apache Zookeeper 註冊中心的簡易啟動器。如果您需要在生產環境中部署註冊中心,請參考生產環境初始化部署一個高可用的註冊中心。
Windows:
./mvnw.cmd clean compile exec:java -pl tools/embedded-zookeeper
Linux / MacOS:
./mvnw clean compile exec:java -pl tools/embedded-zookeeper
Note: You need to open an independent terminal to run, and the command will keep executing.
Docker:
docker run --name some-zookeeper --restart always -d zookeeper
執行上述指令後,稍等片刻,待出現如下圖所示的日誌,即代表註冊中心已啟動,可以繼續進行後續任務。
4. 啟動服務提供者
啟動註冊中心後,下一步是啟動一個對外提供服務的服務提供者。dubbo-samples 中也提供了對應的範例,可透過以下指令快速拉起。
Windows:
./mvnw.cmd clean compile exec:java -pl 1-basic/dubbo-samples-api "-Dexec.mainClass=org.apache.dubbo.samples.provider.Application"
Linux / MacOS:
./mvnw clean compile exec:java -pl 1-basic/dubbo-samples-api -Dexec.mainClass="org.apache.dubbo.samples.provider.Application"
Note: You need to open an independent terminal to run, and the command will keep executing.
執行上述指令後,稍等片刻,待出現如下圖所示的日誌 (DubboBootstrap awaiting
),即代表服務提供者已啟動,表示服務提供者可以對外提供服務。
[19/01/23 03:55:49:049 CST] org.apache.dubbo.samples.provider.Application.main() INFO bootstrap.DubboBootstrap: [DUBBO] DubboBootstrap awaiting ..., dubbo version: 3.2.0 -beta.3, current host: 169.254.44.42
5. 啟動服務消費者
最後一步是啟動一個服務消費者來呼叫服務提供者,這是 RPC 呼叫的核心,為服務消費者呼叫服務提供者提供了橋樑。
Windows:
./mvnw.cmd clean compile exec:java -pl 1-basic/dubbo-samples-api "-Dexec.mainClass=org.apache.dubbo.samples.client.Application"
Linux / MacOS:
./mvnw clean compile exec:java -pl 1-basic/dubbo-samples-api -Dexec.mainClass="org.apache.dubbo.samples.client.Application"
執行上述指令後,稍等片刻,待出現如下圖所示的日誌 (hi, dubbo
),列印的資料是服務提供者處理後返回的,標誌著一次服務呼叫的成功。
Receive result ======> hi, dubbo
延伸閲讀
1. 消費者如何找到伺服器?
在本用例的步驟 3 中,啟動了一個 Zookeeper 註冊中心,服務提供者會將自己的地址寫入註冊中心,供服務消費者獲取。
Dubbo 會將服務提供者的連線資訊寫入 Zookeeper 的 /dubbo/介面名稱
和 /services/應用程式名稱
下。
以下是 Zookeeper 上的資料範例
[zk: localhost:2181(CONNECTED) 5] ls /dubbo/org.apache.dubbo.samples.api.GreetingsService/providers
[dubbo%3A%2F%2F30.221.146.35%3A20880%2Forg.apache.dubbo.samples.api.GreetingsService%3Fanyhost%3Dtrue%26application%3Dfirst-dubbo-provider%26background%3Dfalse%26deprecated%3Dfalse%26dubbo%3D2 .0.2%26dynamic%3Dtrue%26environment%3Dproduct%26generic%3Dfalse%26interface%3Dorg.apache.dubbo.samples.api.GreetingsService%26ipv6%3Dfd00%3A1%3A5%3A5200%3A3218%3A774a%3A4f67%3A23ho1% %26pid%3D85639%26release%3D3.1.4%26service-name-mapping%3Dtrue%26side%3Dprovider%26timestamp%3D1674960780647]
[zk: localhost:2181(CONNECTED) 2] ls /services/first-dubbo-provider
[30.221.146.35:20880]
[zk: localhost:2181(CONNECTED) 3] get /services/first-dubbo-provider/30.221.146.35:20880
{"name":"first-dubbo-provider","id":"30.221.146.35:20880","address":"30.221.146.35","port":20880,"sslPort":null,"payload" :{"@class":"org.apache.dubbo.registry.zookeeper.ZookeeperInstance","id":"30.221.146.35:20880","name":"first-dubbo-provider","metadata":{ "dubbo.endpoints":"[{\"port\":20880,\"protocol\":\"dubbo\"}]", "dubbo.metadata-service.url-params": "{\"connections\ ":\"1\",\"version\":\"1.0.0\",\"dubbo\":\"2.0.2\",\"release\":\"3.1.4\", \"side\":\"provider\",\"ipv6\":\"fd00:1:5:5200:3218:774a:4f67:2341\",\"port\":\"20880\", \"protocol\":\"dubbo\"}","dubbo.metadata.revision":"871fbc9cb2730caea9b0d858852d5ede","dubbo.metadata.storage-type":"local","ipv6":"fd00:1:5 :5200:3218:774a:4f67:2341","timestamp":"1674960780647"}},"registrationTimeUTC":1674960781893,"serviceType":"DYNAMIC","uriSpec":null}
關於 Dubbo 的服務發現模型的更多細節,請參考服務發現。
2. 消費者如何發起請求?
在 Dubbo 的呼叫模型中,連接服務消費者和服務提供者的橋樑是介面。
服務提供者實現指定的介面,服務消費者透過 Dubbo 訂閱該介面。當服務消費者呼叫介面時,Dubbo 會將請求封裝成網路請求,然後發送給服務提供者進行實際的呼叫。
在本用例中,定義了一個介面 GreetingsService
,它有一個名為 sayHi
的方法。
// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/api/GreetingsService.java
package org.apache.dubbo.samples.api;
public interface GreetingsService {
String sayHi(String name);
}
服務消費者可以透過 Dubbo 的 API 取得 GreetingsService
介面的代理,然後以呼叫介面的一般方式進行呼叫。**由於 Dubbo 的動態代理機制,這一切就像本地呼叫一樣。**
// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/client/Application.java
// Get the subscribed Stub
GreetingsService service = reference. get();
// call like a normal java interface
String message = service.sayHi("dubbo");
3. 可以部署多個伺服器嗎?
可以,本節將示範如何啟動伺服器端**叢集**。
要啟動註冊中心,您可以參考實作練習第 3 節的[教學](#3-啟動一個簡單的註冊中心)
修改服務提供者返回的數據,讓第一個啟動的服務提供者返回
hi, dubbo. 我是提供者 1。
修改 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java
檔案的第 25 行,如下所示。
// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java
package org.apache.dubbo.samples.provider;
import org.apache.dubbo.samples.api.GreetingsService;
public class GreetingsServiceImpl implements GreetingsService {
@Override
public String sayHi(String name) {
return "hi, " + name + ". I am provider 1.";
}
}
要啟動第一個服務提供者,您可以參考實作練習第 4 節的[教學](#4-啟動服務提供者)
修改服務提供者返回的數據,讓第二個啟動的服務提供者返回
hi, dubbo. 我是提供者 2。
修改 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java
檔案的第 25 行,如下所示。
// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java
package org.apache.dubbo.samples.provider;
import org.apache.dubbo.samples.api.GreetingsService;
public class GreetingsServiceImpl implements GreetingsService {
@Override
public String sayHi(String name) {
return "hi, " + name + ". I am provider 2.";
}
}
啟動第二個服務提供者,您可以參考實作練習第 4 節的[教學](#4-啟動服務提供者)
要啟動服務消費者,您可以參考實作練習第 5 節的[教學](#5-啟動服務消費者)。如果您多次啟動消費者,您可以看到返回的結果是不同的。
在 dubbo-samples 中,還有一個消費者應用程式 org.apache.dubbo.samples.client.AlwaysApplication
會定期發起呼叫,可以使用以下指令啟動。
Windows:
./mvnw.cmd clean compile exec:java -pl 1-basic/dubbo-samples-api -Dexec.mainClass="org.apache.dubbo.samples.client.AlwaysApplication"
Linux / MacOS:
./mvnw clean compile exec:java -pl 1-basic/dubbo-samples-api -Dexec.mainClass="org.apache.dubbo.samples.client.AlwaysApplication"
啟動後,您可以看到類似以下的日誌。消費者會隨機呼叫不同的服務提供者,返回的結果也是遠端服務提供者預期的結果。
Sun Jan 29 11:23:37 CST 2023 Receive result ======> hi, dubbo. I am provider 1.
Sun Jan 29 11:23:38 CST 2023 Receive result ======> hi, dubbo. I am provider 2.
Sun Jan 29 11:23:39 CST 2023 Receive result ======> hi, dubbo. I am provider 2.
Sun Jan 29 11:23:40 CST 2023 Receive result ======> hi, dubbo. I am provider 1.
Sun Jan 29 11:23:41 CST 2023 Receive result ======> hi, dubbo. I am provider 1.
4. 這個用例複雜嗎?
不,Dubbo 只需要簡單的配置即可實現穩定高效的遠端呼叫。
以下是一個服務提供者的簡單範例,只需定義一些配置即可啟動。
// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/Application.java
// define all services
ServiceConfig<GreetingsService> service = new ServiceConfig<>();
service.setInterface(GreetingsService.class);
service.setRef(new GreetingsServiceImpl());
// start Dubbo
DubboBootstrap. getInstance()
.application("first-dubbo-provider")
.registry(new RegistryConfig(ZOOKEEPER_ADDRESS))
.protocol(new ProtocolConfig("dubbo", -1))
.service(service)
.start();
以下是一個服務消費者的簡單範例。定義幾個配置後,啟動後即可取得對應的代理物件。之後,使用者完全不需要感知這個物件背後的複雜實現。**一切都只需要與本地呼叫相同。**
// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/client/Application.java
// define all subscriptions
ReferenceConfig<GreetingsService> reference = new ReferenceConfig<>();
reference.setInterface(GreetingsService.class);
// start Dubbo
DubboBootstrap. getInstance()
.application("first-dubbo-consumer")
.registry(new RegistryConfig(ZOOKEEPER_ADDRESS))
.reference(reference)
.start();
// Get the subscribed Stub
GreetingsService service = reference. get();
// call like a normal java interface
String message = service.sayHi("dubbo");
更多
這個用例介紹了 RPC 遠端呼叫的基本流程,並透過啟動三個節點:註冊中心、服務提供者和服務消費者,模擬了一個微服務部署架構。
在下一份教學中,我們將會說明服務提供者和服務消費者的配置,並告訴您如何從零開始構建一個微服務應用程式。