博客 / 詳情

返回

tio-boot整合Dubbo

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
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

註解解釋

  1. @AService: 這是 JFinal AOP 的一個註解,用於標記一個類為服務類(Service),並且這個類可以被 JFinal 的 AOP 容器管理。@AService註解的作用類似於 Spring 中的@Service註解,它告訴框架這是一個服務層的組件,需要被框架管理和依賴注入。
  2. @AAutowired: 這是 JFinal AOP 中的自動注入註解,類似於 Spring 中的@Autowired。它用於自動將接口類型的依賴注入到類中。使用這個註解,可以讓 JFinal AOP 容器自動將對應的實現類注入到標註了@AAutowired的屬性中。
  3. @RequestPath: 這個註解來自於 Tio-boot 框架,用於定義 HTTP 請求的路徑。標記在類上時,它定義了這個類處理的請求路徑的前綴;標記在方法上時,它定義了具體方法處理的請求路徑。如果方法上沒有指定路徑,那麼它會使用類上的路徑作為請求路徑。
  4. @AComponentScan: 這個註解用於指定 JFinal AOP 需要掃描的包路徑。通過這個註解,框架會自動掃描並註冊指定包路徑下的所有組件(如@AService標註的類),以便實現依賴注入。

注入流程

  1. 掃描服務類: @AComponentScan會掃描指定包下的所有類,找到帶有@AService註解的類(如HelloServiceImpl),並將它們註冊到 JFinal AOP 的容器中。
  2. 處理依賴注入: 在IndexController中,由於helloService屬性被標註了@AAutowired,JFinal AOP 會查找容器中是否有HelloService接口的實現類。如果找到,就將這個實現類的實例(即HelloServiceImpl)注入到helloService屬性中。
  3. 啓動 Tio-boot: TioApplication.run(ProviderApp.class, args); 會啓動 Tio-boot 應用。這個過程中,Tio-boot 會啓動一個內嵌的 HTTP 服務器,在啓動過程中,所有標記了註解的類都會被加載和初始化,確保依賴注入完成後,並加載所有的控制器(如IndexController),準備處理客户端的 HTTP 請求。

訪問結果

當你訪問http://localhost/時,HTTP 請求會被路由到IndexControllerindex()方法。由於helloService已經被注入為HelloServiceImpl的實例,因此helloService.sayHello("Tong Li")會調用HelloServiceImplsayHello方法,並返回"Hello Tong Li"。最終,這個字符串會作為 HTTP 響應返回給客户端。

安裝 zookpper

dubbo 使用 zookpper 作為註冊中心,所以需要安裝 zookeeper

  1. 下載 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
  1. 解壓
tar -zxf apache-zookeeper-3.7.2-bin.tar.gz -C /opt/
  1. 進入解壓後的目錄
cd /opt/apache-zookeeper-3.7.2-bin
  1. 配置 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
  1. 啓動 ZooKeeper
bin/zkServer.sh start
  1. 檢查 ZooKeeper 狀態
bin/zkServer.sh status

如果 ZooKeeper 正常運行,你會看到類似如下輸出:

Mode: standalone
  1. zookeerp 端口
8080
33125
2181
  1. 關閉 zookeeper
bin/zkServer.sh stop
  1. 開機自啓
    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-boot
  • jfinal-aop
  • dubbo(移除與 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
服務實現類

編寫 HelloServiceHiService 的實現類:

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");
  }
}

啓動流程

  1. 啓動服務提供者

    • ProviderApp 啓動時,TioApplication.run 方法會啓動 Tio 框架的內嵌服務器,並掃描帶有 @AService 註解的類(如 HelloServiceImplHiServiceImpl)。
    • DubboProviderConfig 類中的 config() 方法會配置 Dubbo 的應用、註冊中心和服務提供者,並通過 DubboProvider 類的 export() 方法將服務發佈到註冊中心。
  2. 啓動服務消費者

    • ConsumerApp 啓動時,TioApplication.run 會啓動消費者模塊,並通過 DubboConsumerConfig 類的 config() 方法配置 Dubbo 應用和註冊中心。
    • Dubbo.get(HelloService.class)Dubbo.get(HiService.class) 方法會從註冊中心獲取服務提供者的引用,以便在消費者中調用。

服務調用流程

  1. 服務消費者通過 Dubbo.get(HelloService.class) 獲取 HelloService 的遠程服務引用。
  2. 當消費者調用 HelloService.sayHello("Tong Li") 時,Dubbo 框架會通過註冊中心獲取服務提供者的地址,並將請求發送到相應的服務提供者。
  3. 服務提供者接收到請求後,調用 HelloServiceImpl.sayHello("Tong Li") 方法,返回結果 "Hello Tong Li"
  4. 最終,消費者接收到響應,並將結果返回給調用者。
user avatar mokeywie 頭像 mo_or 頭像 tracy_5cb7dfc1f3f67 頭像 goudantiezhuerzi 頭像 saoming_zhang 頭像 jacheut 頭像 ixuea 頭像 nahandechaomian 頭像 codecraft 頭像 seazhan 頭像 dolphinscheduler 頭像 chengxy 頭像
22 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.