tio-boot官網
概述
什麼是 Dubbo
Apache Dubbo 是一款 RPC 服務開發框架,用於解決微服務架構下的服務治理與通信問題,官方提供了 Java、Golang 等多語言 SDK 實現。使用 Dubbo 開發的微服務原生具備相互之間的遠程地址發現與通信能力, 利用 Dubbo 提供的豐富服務治理特性,可以實現諸如服務發現、負載均衡、流量調度等服務治理訴求。Dubbo 被設計為高度可擴展,用户可以方便的實現流量攔截、選址的各種定製邏輯。
在雲原生時代,Dubbo 相繼衍生出了 Dubbo3、Proxyless Mesh 等架構與解決方案,在易用性、超大規模微服務實踐、雲原生基礎設施適配、安全性等幾大方向上進行了全面升級。
dubbo 官網
https://dubbo.apache.org/
tio-boot 整合 Dubbo
- 筆者對在 jfinal-aop 框架使用 dubbo 做了支持,使得使用 dubbo 方便
-
所以使用是需要 添加 jfinal-aop 依賴
Introduction
Dubbo 作為一款微服務框架,最重要的是向用户提供跨進程的 RPC 遠程調用能力。如上圖所示,Dubbo 的服務消費者(Consumer)通過一系列的工作將請求發送給服務提供者(Provider)。
為了實現這樣一個目標,Dubbo 引入了註冊中心(Registry)組件,通過註冊中心,服務消費者可以感知到服務提供者的連接方式,從而將請求發送給正確的服務提供者。
tio-boot 整合 jfinal-aop 依賴注入示例
添加依賴
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>tio-boot</artifactId>
<version>${tio-boot.version}</version>
</dependency>
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>jfinal-aop</artifactId>
<version>1.2.6</version>
</dependency>
整合示例
編寫接口
package com.litongjava.tio.duboot.demo001.service;
public interface HelloService {
String sayHello(String name);
}
編寫實現類
package com.litongjava.tio.duboot.demo001.service.impl;
import com.litongjava.jfinal.aop.annotation.AService;
import com.litongjava.tio.duboot.demo001.service.HelloService;
@AService
public class HelloServiceImpl implements HelloService {
public String sayHello(String name) {
return "Hello " + name;
}
}
編寫 Controller 調用接口
package com.litongjava.tio.duboot.demo001.controller;
import com.litongjava.jfinal.aop.annotation.AAutowired;
import com.litongjava.tio.duboot.demo001.service.HelloService;
import com.litongjava.tio.http.server.annotation.RequestPath;
@RequestPath("/")
public class IndexController {
@AAutowired
private HelloService helloService;
@RequestPath()
public String index() {
return helloService.sayHello("Tong Li");
}
}
編寫啓動類進行掃描,注入和啓動
package com.litongjava.tio.duboot.demo001;
import com.litongjava.jfinal.aop.annotation.AComponentScan;
import com.litongjava.tio.boot.TioApplication;
@AComponentScan
public class ProviderApp {
public static void main(String[] args) {
long start = System.currentTimeMillis();
TioApplication.run(ProviderApp.class, args);
long end = System.currentTimeMillis();
System.out.println((end - start) + "ms");
}
}
訪問測試 http://localhost/返回如下
Hello Tong Li
註解解釋
- @AService: 這是 JFinal AOP 的一個註解,用於標記一個類為服務類(Service),並且這個類可以被 JFinal 的 AOP 容器管理。
@AService註解的作用類似於 Spring 中的@Service註解,它告訴框架這是一個服務層的組件,需要被框架管理和依賴注入。 - @AAutowired: 這是 JFinal AOP 中的自動注入註解,類似於 Spring 中的
@Autowired。它用於自動將接口類型的依賴注入到類中。使用這個註解,可以讓 JFinal AOP 容器自動將對應的實現類注入到標註了@AAutowired的屬性中。 - @RequestPath: 這個註解來自於 Tio-boot 框架,用於定義 HTTP 請求的路徑。標記在類上時,它定義了這個類處理的請求路徑的前綴;標記在方法上時,它定義了具體方法處理的請求路徑。如果方法上沒有指定路徑,那麼它會使用類上的路徑作為請求路徑。
- @AComponentScan: 這個註解用於指定 JFinal AOP 需要掃描的包路徑。通過這個註解,框架會自動掃描並註冊指定包路徑下的所有組件(如
@AService標註的類),以便實現依賴注入。
注入流程
- 掃描服務類:
@AComponentScan會掃描指定包下的所有類,找到帶有@AService註解的類(如HelloServiceImpl),並將它們註冊到 JFinal AOP 的容器中。 - 處理依賴注入: 在
IndexController中,由於helloService屬性被標註了@AAutowired,JFinal AOP 會查找容器中是否有HelloService接口的實現類。如果找到,就將這個實現類的實例(即HelloServiceImpl)注入到helloService屬性中。 - 啓動 Tio-boot:
TioApplication.run(ProviderApp.class, args);會啓動 Tio-boot 應用。這個過程中,Tio-boot 會啓動一個內嵌的 HTTP 服務器,在啓動過程中,所有標記了註解的類都會被加載和初始化,確保依賴注入完成後,並加載所有的控制器(如IndexController),準備處理客户端的 HTTP 請求。
訪問結果
當你訪問http://localhost/時,HTTP 請求會被路由到IndexController的index()方法。由於helloService已經被注入為HelloServiceImpl的實例,因此helloService.sayHello("Tong Li")會調用HelloServiceImpl的sayHello方法,並返回"Hello Tong Li"。最終,這個字符串會作為 HTTP 響應返回給客户端。
安裝 zookpper
dubbo 使用 zookpper 作為註冊中心,所以需要安裝 zookeeper
- 下載 ZooKeeper
你可以從 ZooKeeper 官方網站 下載最新版本的 ZooKeeper。
mkdir /opt/package/zookeeper -p &&cd /opt/package/zookeeper
wget https://downloads.apache.org/zookeeper/zookeeper-3.7.2/apache-zookeeper-3.7.2-bin.tar.gz
- 解壓
tar -zxf apache-zookeeper-3.7.2-bin.tar.gz -C /opt/
- 進入解壓後的目錄
cd /opt/apache-zookeeper-3.7.2-bin
- 配置 ZooKeeper
在 conf 目錄下複製 zoo_sample.cfg 並重命名為 zoo.cfg。
cp conf/zoo_sample.cfg conf/zoo.cfg
編輯 zoo.cfg 配置文件:
vi conf/zoo.cfg
根據需要修改以下配置項:
tickTime = 2000
dataDir = /var/lib/zookeeper
clientPort = 2181
- 啓動 ZooKeeper
bin/zkServer.sh start
- 檢查 ZooKeeper 狀態
bin/zkServer.sh status
如果 ZooKeeper 正常運行,你會看到類似如下輸出:
Mode: standalone
- zookeerp 端口
8080
33125
2181
- 關閉 zookeeper
bin/zkServer.sh stop
- 開機自啓
zkServer.sh 命令參數
Usage: ./bin/zkServer.sh [--config <conf-dir>] {start|start-foreground|stop|version|restart|status|print-cmd}
vi /lib/systemd/system/zookeeper.service
[Unit]
Description=zookeeper
After=network.target
[Service]
Type=simple
Restart=on-failure
RestartSec=5s
WorkingDirectory=/opt/apache-zookeeper-3.7.2-bin
Environment="JAVA_HOME=/usr/java/jdk1.8.0_211"
ExecStart=/opt/apache-zookeeper-3.7.2-bin/bin/zkServer.sh start-foreground
[Install]
WantedBy=multi-user.target
注意上面的環境變量 JAVA_HOME
systemctl start zookeeper
systemctl enable zookeeper
systemctl status zookeeper
tio-boot 整合 Dubbo 示例
創建工程
在本示例中,我們將創建三個獨立的工程:
tio-boot-dubbo-2-6-0-demo01-api:API 模塊tio-boot-dubbo-2-6-0-demo01-provider:服務提供者模塊tio-boot-dubbo-2-6-0-demo01-consumer:服務消費者模塊
tio-boot-dubbo-2-6-0-demo01-api
這個模塊僅包含服務的接口定義。例如:
package com.litongjava.tio.duboot.demo001.service;
public interface HelloService {
String sayHello(String name);
}
package com.litongjava.tio.dubbo.demo001.service;
public interface HiService {
String sayHi(String name);
}
tio-boot-dubbo-2-6-0-demo01-provider
添加依賴
在服務提供者模塊中,我們需要添加以下依賴:
logback-classic:日誌框架tio-bootjfinal-aopdubbo(移除與spring-boot相關的依賴)zkclient:zookeeper 客户端
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>tio-boot-dubbo-2-6-0-demo01-api</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>tio-boot</artifactId>
<version>${tio-boot.version}</version>
</dependency>
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>jfinal-aop</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.0</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.9</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
配置文件
在 app.properties 中添加如下配置:
server.port=8000
app.name=service-provider
ZOOKEEPER_URL=zookeeper://192.168.3.9:2181
服務實現類
編寫 HelloService 和 HiService 的實現類:
package com.litongjava.tio.dubbo.demo001.service.impl;
import com.litongjava.jfinal.aop.annotation.AService;
import com.litongjava.tio.dubbo.demo001.service.HelloService;
@AService
public class HelloServiceImpl implements HelloService {
public String sayHello(String name) {
return "Hello " + name;
}
}
package com.litongjava.tio.dubbo.demo001.service.impl;
import com.litongjava.tio.dubbo.demo001.service.HiService;
public class HiServiceImpl implements HiService {
@Override
public String sayHi(String name) {
return "Hi " + name;
}
}
Dubbo 配置
編寫 DubboProviderConfig 類進行 Dubbo 配置:
package com.litongjava.tio.dubbo.demo001.config;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.qos.common.Constants;
import com.alibaba.dubbo.qos.server.Server;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.jfinal.aop.annotation.AConfiguration;
import com.litongjava.jfinal.aop.annotation.AInitialization;
import com.litongjava.jfinal.dubbo.DubboProvider;
import com.litongjava.tio.boot.constatns.TioBootConfigKeys;
import com.litongjava.tio.boot.server.TioBootServer;
import com.litongjava.tio.dubbo.demo001.service.HelloService;
import com.litongjava.tio.dubbo.demo001.service.HiService;
import com.litongjava.tio.dubbo.demo001.service.impl.HelloServiceImpl;
import com.litongjava.tio.dubbo.demo001.service.impl.HiServiceImpl;
import com.litongjava.tio.utils.environment.EnvUtils;
import com.litongjava.tio.utils.thread.TioThreadUtils;
@AConfiguration
public class DubboProviderConfig {
@AInitialization
public void config() {
// 防止 QoS 端口衝突
System.setProperty("dubbo.application.logger", "slf4j");
System.setProperty(Constants.QOS_PORT, 2223 + "");
System.setProperty(Constants.ACCEPT_FOREIGN_IP, "false");
// 創建應用配置
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName(EnvUtils.get(TioBootConfigKeys.APP_NAME));
// 創建註冊中心配置
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress(EnvUtils.get(TioBootConfigKeys.ZOOKEEPER_URL));
// 創建服務提供者配置
ProviderConfig providerConfig = new ProviderConfig();
// 初始化
DubboProvider.init(applicationConfig, registryConfig, providerConfig);
// 添加服務
DubboProvider.add(HelloService.class, Aop.get(HelloServiceImpl.class));
DubboProvider.add(HiService.class, Aop.get(HiServiceImpl.class));
// 導出服務
TioThreadUtils.submit(() -> {
DubboProvider.export();
// 啓動後關閉 QoS 服務
Server.getInstance().stop();
});
// 服務銷燬時取消導出
TioBootServer.me().addDestroyMethod(() -> {
DubboProvider.unexport();
});
}
}
啓動類
編寫 ProviderApp 啓動類:
package com.litongjava.tio.dubbo.demo001;
import com.litongjava.jfinal.aop.annotation.AComponentScan;
import com.litongjava.tio.boot.TioApplication;
@AComponentScan
public class ProviderApp {
public static void main(String[] args) {
long start = System.currentTimeMillis();
TioApplication.run(ProviderApp.class, args);
long end = System.currentTimeMillis();
System.out.println((end - start) + "ms");
}
}
tio-boot-dubbo-2-6-0-demo01-consumer
配置文件
在 app.properties 中添加如下配置:
server.port=7000
app.name=service-consumer
ZOOKEEPER_URL=zookeeper://192.168.3.9:2181
Dubbo 配置
編寫 DubboConsumerConfig 類進行 Dubbo 配置:
package com.litongjava.tio.web.hello.config;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.qos.common.Constants;
import com.alibaba.dubbo.qos.server.Server;
import com.litongjava.jfinal.aop.annotation.AConfiguration;
import com.litongjava.jfinal.aop.annotation.AInitialization;
import com.litongjava.jfinal.dubbo.Dubbo;
import com.litongjava.tio.boot.constatns.TioBootConfigKeys;
import com.litongjava.tio.boot.server.TioBootServer;
import com.litongjava.tio.dubbo.demo001.service.HelloService;
import com.litongjava.tio.dubbo.demo001.service.HiService;
import com.litongjava.tio.utils.environment.EnvUtils;
@AConfiguration
public class DubboConsumerConfig {
@AInitialization
public void config() {
// 配置日誌系統
System.setProperty("dubbo.application.logger", "slf4j");
// 防止 QoS 端口衝突
System.setProperty(Constants.QOS_PORT, 2224 + "");
System.setProperty(Constants.ACCEPT_FOREIGN_IP, "false");
// 創建應用配置
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName(EnvUtils.get(TioBootConfigKeys.APP
_NAME));
// 創建註冊中心配置
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress(EnvUtils.get(TioBootConfigKeys.ZOOKEEPER_URL));
// 設置 Dubbo 配置
Dubbo.setApplication(applicationConfig);
Dubbo.setRegistry(registryConfig);
// 獲取服務
Dubbo.get(HelloService.class);
Dubbo.get(HiService.class);
// 啓動後關閉 QoS 服務
Server.getInstance().stop();
TioBootServer.me().addDestroyMethod(() -> {
Dubbo.clear();
});
}
}
控制器類
編寫 IndexController 控制器類:
package com.litongjava.tio.web.hello.controller;
import com.litongjava.jfinal.dubbo.Dubbo;
import com.litongjava.tio.dubbo.demo001.service.HelloService;
import com.litongjava.tio.dubbo.demo001.service.HiService;
import com.litongjava.tio.http.server.annotation.RequestPath;
@RequestPath("/")
public class IndexController {
@RequestPath()
public String index() {
HelloService helloService = Dubbo.get(HelloService.class);
HiService hiService = Dubbo.get(HiService.class);
return helloService.sayHello("Tong Li") + "_" + hiService.sayHi("Tong Li");
}
}
啓動類
編寫 ConsumerApp 啓動類:
package com.litongjava.tio.web.hello;
import com.litongjava.jfinal.aop.annotation.AComponentScan;
import com.litongjava.tio.boot.TioApplication;
@AComponentScan
public class ConsumerApp {
public static void main(String[] args) {
long start = System.currentTimeMillis();
TioApplication.run(ConsumerApp.class, args);
long end = System.currentTimeMillis();
System.out.println((end - start) + "ms");
}
}
啓動流程
-
啓動服務提供者:
ProviderApp啓動時,TioApplication.run方法會啓動 Tio 框架的內嵌服務器,並掃描帶有@AService註解的類(如HelloServiceImpl和HiServiceImpl)。DubboProviderConfig類中的config()方法會配置 Dubbo 的應用、註冊中心和服務提供者,並通過DubboProvider類的export()方法將服務發佈到註冊中心。
-
啓動服務消費者:
ConsumerApp啓動時,TioApplication.run會啓動消費者模塊,並通過DubboConsumerConfig類的config()方法配置 Dubbo 應用和註冊中心。Dubbo.get(HelloService.class)和Dubbo.get(HiService.class)方法會從註冊中心獲取服務提供者的引用,以便在消費者中調用。
服務調用流程
- 服務消費者通過
Dubbo.get(HelloService.class)獲取HelloService的遠程服務引用。 - 當消費者調用
HelloService.sayHello("Tong Li")時,Dubbo 框架會通過註冊中心獲取服務提供者的地址,並將請求發送到相應的服務提供者。 - 服務提供者接收到請求後,調用
HelloServiceImpl.sayHello("Tong Li")方法,返回結果"Hello Tong Li"。 - 最終,消費者接收到響應,並將結果返回給調用者。