1. 程式人生 > 實用技巧 >Dubbo 01 基礎概念與入門工程搭建

Dubbo 01 基礎概念與入門工程搭建

Dubbo 01 基礎概念與入門工程搭建

1. 概述基本概念

定義

Apache Dubbo |ˈdʌbəʊ| 是一款高效能、輕量級的開源 Java RPC 框架,它提供了三大核心能力:

  1. 面向介面的遠端方法呼叫
  2. 智慧容錯和負載均衡
  3. 以及服務自動註冊和發現。

架構

角色

  1. Registry 註冊中心,用於服務的註冊與發現。
  2. Provider 服務提供者,通過向 Registry 註冊服務。
  3. Consumer 服務消費者,通過從 Registry 發現服務。後續直接呼叫 Provider ,無需經過 Registry 。
  4. Monitor 監控中心,統計服務的呼叫次數和呼叫時間。
  5. Container 服務執行容器。

呼叫關係

  1. 服務容器負責啟動,載入,執行服務提供者。
  2. 服務提供者在啟動時,向註冊中心註冊自己提供的服務。
  3. 服務消費者在啟動時,向註冊中心訂閱自己所需的服務。
  4. 註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連線推送變更資料給消費者。
  5. 服務消費者,從提供者地址列表中,基於軟負載均衡演算法,選一臺提供者進行呼叫,如果呼叫失敗,再選另一臺呼叫。
  6. 服務消費者和提供者,在記憶體中累計呼叫次數和呼叫時間,定時每分鐘傳送一次統計資料到監控中心。

2. 入門工程搭建

2.0 安裝Zookeeper

以本機為例:官網下載包,安裝後有如下環境:

  • 埠:2181
  • 安裝地址:E:\apache-zookeeper-3.6.1\bin
  • 啟動服務:E:\apache-zookeeper-3.6.1\bin\zkServer.cmd
  • 客戶端: E:\apache-zookeeper-3.6.1\bin\zkCli.cmd

2.1 XML方式

dubbo-xml-demo
    ├─user-rpc-service-api
    ├─user-rpc-service-consumer
    └─user-rpc-service-provider

2.1.1 Api

user-rpc-service-api 專案,服務介面,定義 Dubbo Service API 介面,提供給消費者使用。

  1. UserDTO

nb\yucai\dubbo\nacosdemo\dto下,新建UserDTO模擬傳輸物件

@Data
public class UserDTO implements Serializable {
    
    /**
     * 使用者編號
     */
    private Integer id;

    /**
     * 暱稱
     */
    private String name;

    /**
     * 性別
     */
    private Integer gender;

    public UserDTO setName(String name) {
        this.name = name;
        return this;
    }

    public UserDTO setId(Integer id) {
        this.id = id;
        return this;
    }

    public UserDTO setGender(Integer gender) {
        this.gender = gender;
        return this;
    }
}
  1. UserRpcService

nb\yucai\dubbo\nacosdemo新建UserRpcService.java

public interface UserRpcService {
    /**
     * 根據指定使用者編號,獲得使用者資訊
     *
     * @param id 使用者編號
     * @return 使用者資訊
     */
    UserDTO get(Integer id);

    Integer add(UserDTO dto);
}

2.1.2 Provide

  1. pom.xml新增如下依賴
<!-- 引入定義的 Dubbo API 介面 -->
<dependency>
    <groupId>nb.yucai</groupId>
    <artifactId>user-rpc-service-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

<!-- 引入 Spring Boot 依賴 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

<!-- 實現對 Dubbo 的自動化配置 -->
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.7.4.1</version>
</dependency>
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>2.7.4.1</version>
</dependency>

<!-- 使用 Zookeeper 作為註冊中心 -->
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>2.13.0</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>2.13.0</version>
</dependency>
  1. application.yml中新增dubbo配置
# dubbo 配置項,對應 DubboConfigurationProperties 配置類
dubbo:
  # Dubbo 應用配置
  application:
    name: user-service-provider # 應用名
  # Dubbo 註冊中心配
  registry:
    address: zookeeper://127.0.0.1:2181 # 註冊中心地址。個鞥多註冊中心,可見 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文件。
  # Dubbo 服務提供者協議配置
  protocol:
    port: -1 # 協議埠。使用 -1 表示隨機埠。
    name: dubbo # 使用 `dubbo://` 協議。更多協議,可見 http://dubbo.apache.org/zh-cn/docs/user/references/protocol/introduction.html 文件
  # Dubbo 服務提供者配置
  provider:
    timeout: 1000 # 【重要】遠端服務呼叫超時時間,單位:毫秒。預設為 1000 毫秒,胖友可以根據自己業務修改
    filter: -exception # 去掉 ExceptionFilter
    UserRpcService:
      version: 1.0.0
    # validation: true 開啟將驗證所有Service的引數

  1. UserRpcServiceImpl

在nb.yucai.dubbo.nacosdemo.service包下建立UserRpcService的實現類

@Service
public class UserRpcServiceImpl implements UserRpcService {

    @Override
    public UserDTO get(Integer id) {
        return new UserDTO().setId(id)
                .setName("沒有暱稱:" + id)
                .setGender(id % 2 + 1); // 1 - 男;2 - 女
    }

    @Override
    public Integer add(UserDTO dto) {
        if("yucai".equals(dto.getName())){
            throw new ServiceException(ServiceExceptionEnum.USER_EXISTS);
        }
        return Math.toIntExact(System.currentTimeMillis() / 1000);
    }
}

  1. 新建Dubbo.xml的配置檔案:src\main\resources\dubbo.xml

<dubbo:service/>可以註冊為Dubbo服務的提供者

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo
       http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 服務提供者暴露服務配置 -->
    <dubbo:service ref="userRpcServiceImpl" interface="nb.yucai.dubbo.nacosdemo.UserRpcService"
        version="${dubbo.provider.UserRpcService.version}" validation="true" />

</beans>
  1. ProviderApplication

ProviderApplication類啟動專案,提供Dubbo服務

@SpringBootApplication
@ImportResource("classpath:dubbo.xml") //讀取Dubbo配置檔案
public class ProviderApplication {

    public static void main(String[] args) {
        // 啟動 Spring Boot 應用
        SpringApplication.run(ProviderApplication.class, args);
    }

}

此時連結Zookeeper,輸入命令ls /dubbo可以看到服務UserRpcService即為成功

2.1.3 Consumer

  1. pom.xml引入依賴
<!-- 引入定義的 Dubbo API 介面 -->
<dependency>
    <groupId>nb.yucai</groupId>
    <artifactId>user-rpc-service-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

<!-- 引入 Spring Boot 依賴 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

<!-- 實現對 Dubbo 的自動化配置 -->
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.7.4.1</version>
</dependency>
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>2.7.4.1</version>
</dependency>

<!-- 使用 Zookeeper 作為註冊中心 -->
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>2.13.0</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>2.13.0</version>
</dependency>
  1. 配置檔案
    resource下建立application.yml檔案,新增Dubbo相關的配置,如下所示
# dubbo 配置項,對應 DubboConfigurationProperties 配置類
dubbo:
  # Dubbo 應用配置
  application:
    name: user-service-consumer # 應用名
  # Dubbo 註冊中心配置
  registry:
    address: zookeeper://127.0.0.1:2181 # 註冊中心地址。個鞥多註冊中心,可見 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文件。
  # Dubbo 消費者配置
  consumer:
    timeout: 1000 # 【重要】遠端服務呼叫超時時間,單位:毫秒。預設為 1000 毫秒,胖友可以根據自己業務修改
    UserRpcService:
      version: 1.0.0
  1. 配置XML檔案,新增Dubbo的Service服務引用者
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo
       http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 服務提供者暴露服務配置 -->
    <dubbo:reference interface="nb.yucai.dubbo.nacosdemo.UserRpcService" id="userService"
                     version="${dubbo.consumer.UserRpcService.version}" validation="true"/>
</beans>
  1. ConsumerApplication
    建立 ConsumerApplication 類,用於啟動該專案,呼叫 Dubbo 服務。
  • 在類上,新增 @ImportResource 註解,引入 dubbo.xml 配置檔案。
  • 在 UserRpcServiceTest 中,我們使用 @Resource 註解,引用通過 <dubbo:reference /> 配置的引用的 UserRpcService 服務對應的 UserRpcService Bean 。
@SpringBootApplication
@ImportResource("classpath:dubbo.xml")
public class ConsumerApplication {

    public static void main(String[] args) {
        // 啟動 Spring Boot 應用
        ConfigurableApplicationContext context = SpringApplication.run(ConsumerApplication.class, args);
    }

    @Component
    public class UserRpcServiceTest implements CommandLineRunner {

        private final Logger logger = LoggerFactory.getLogger(getClass());

        @Resource
        private UserRpcService userRpcService;

        @Override
        public void run(String... args) throws Exception {
            UserDTO user = userRpcService.get(1);
            logger.info("[run][發起一次 Dubbo RPC 請求,獲得使用者為({})]", user);
        }

    }
}|

註解方式

工程結構如下

dubbo-api-demo
    ├─user-apirpc-service-api
    ├─user-apirpc-service-consumer
    └─user-apirpc-service-provider

Api

基本與XML方式實現一致,可參考上文

Provider

  1. 引入依賴

基本與XML方式實現一致,可參考上文

  1. 應用配置檔案
    application.yml中新增如下程式碼:
# dubbo 配置項,對應 DubboConfigurationProperties 配置類
dubbo:
  # Dubbo 應用配置
  application:
    name: user-service-provider # 應用名
  # Dubbo 註冊中心配
  registry:
    address: zookeeper://127.0.0.1:2181 # 註冊中心地址。個鞥多註冊中心,可見 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文件。
  # Dubbo 服務提供者協議配置
  protocol:
    port: -1 # 協議埠。使用 -1 表示隨機埠。
    name: dubbo # 使用 `dubbo://` 協議。更多協議,可見 http://dubbo.apache.org/zh-cn/docs/user/references/protocol/introduction.html 文件
  # Dubbo 服務提供者配置
  provider:
    timeout: 1000 # 【重要】遠端服務呼叫超時時間,單位:毫秒。預設為 1000 毫秒,胖友可以根據自己業務修改
    filter: -exception # 去掉 ExceptionFilter
    UserRpcService:
      version: 1.0.0
  scan:
    base-packages: nb.yucai.dubbo.apidemo.service

多的是dubbo:scan:base-packages配置, Dubbo將根據此配置查詢Dubbo中定義的@Service修飾的類,並將其暴露為Dubbo服務的提供者。因此,無需配置Dubbo的XML檔案進行配置

  1. UserRpcServiceImpl
    建立Dubbo的Service實現類:nb.yucai.dubbo.apidemo.service.UserRpcServiceImpl
import org.apache.dubbo.config.annotation.Service;

@Service(version = "${dubbo.provider.UserRpcService.version}")
public class UserRpcServiceImpl implements UserRpcService {

    @Override
    public UserDTO get(Integer id) {
        return new UserDTO().setId(id)
                .setName("沒有暱稱:" + id)
                .setGender(id % 2 + 1); // 1 - 男;2 - 女
    }
}
  1. ProviderApplication

正常建立即可,無需新增@ImportResource註解,引入dubbo.xml即可

Consumer

  1. 引入依賴

基本與XML方式實現一致,可參考上文

  1. 應用配置檔案

application.yml中新增

# dubbo 配置項,對應 DubboConfigurationProperties 配置類
dubbo:
  # Dubbo 應用配置
  application:
    name: user-service-consumer # 應用名
  # Dubbo 註冊中心配置
  registry:
    address: zookeeper://127.0.0.1:2181 # 註冊中心地址。個鞥多註冊中心,可見 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文件。
  # Dubbo 消費者配置
  consumer:
    timeout: 1000 # 【重要】遠端服務呼叫超時時間,單位:毫秒。預設為 1000 毫秒,胖友可以根據自己業務修改
    UserRpcService:
      version: 1.0.0
  1. ConsumerApplication

建立ConsumerApplication類

@SpringBootApplication
@Slf4j
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class);
    }

    @Component
    public class UserRpcServiceTest implements CommandLineRunner {


        @Reference(version = "${dubbo.consumer.UserRpcService.version}")
        private UserRpcService userRpcService;

        public void run(String... args) throws Exception {
            UserDTO user = userRpcService.get(1);
            log.info("[run][發起一次 Dubbo RPC 請求,獲得使用者為({})", user);
        }

    }
}
  • 在類上,無需新增 @ImportResource 註解,引入 dubbo.xml 配置檔案。
  • 在 UserRpcServiceTest 中,我們使用 Dubbo 定義的 @Reference註解,“直接”引用的 UserRpcService 服務對應的 UserRpcService Bean 。並且,在該註解裡,我們可以新增該 Service 服務的配置。當然,每個屬性和 <dubbo:reference /> 標籤是基本一致的。

3. 整合開源元件

整合Nacos

Nacos 致力於幫助您發現、配置和管理微服務。Nacos 提供了一組簡單易用的特性集,幫助您快速實現動態服務發現、服務配置、服務元資料及流量管理。Nacos 幫助您更敏捷和容易地構建、交付和管理微服務平臺。 Nacos 是構建以“服務”為中心的現代應用架構 (例如微服務正規化、雲原生正規化) 的服務基礎設施。

本小節進行 Dubbo 和 Nacos 的整合,使用 Nacos 作為 Dubbo 的註冊中心。
Dubbo 提供了 dubbo-registry-nacos 子專案,已經對 Nacos 進行適配,所以我們只要引入它,基本就完成了 Dubbo 和 Nacos 的整合,賊方便。

  1. Nacos官網下載,執行即可。

  2. API

以上文註解式配置的方法為例,仍採用上述Service,無需改動

  1. Provider
    引入依賴
<!-- 使用 Zookeeper 作為註冊中心 -->
<!--<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>2.13.0</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>2.13.0</version>
</dependency>-->
<!-- 使用 Nacos 作為註冊中心 -->
<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-client</artifactId>
    <version>1.2.1</version>
</dependency>
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-registry-nacos</artifactId>
    <version>2.7.4.1</version>
</dependency>

application.yml中配置註冊中心為Nacos:

# dubbo 配置項,對應 DubboConfigurationProperties 配置類
dubbo:
  # Dubbo 應用配置
  application:
    name: user-service-provider # 應用名
  # Dubbo 註冊中心配
  registry:
    address: nacos://99.11.6.32:8848 # 註冊中心地址。個鞥多註冊中心,可見 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文件。
  # Dubbo 服務提供者協議配置
  protocol:
    port: -1 # 協議埠。使用 -1 表示隨機埠。
    name: dubbo # 使用 `dubbo://` 協議。更多協議,可見 http://dubbo.apache.org/zh-cn/docs/user/references/protocol/introduction.html 文件
  # Dubbo 服務提供者配置
  provider:
    timeout: 1000 # 【重要】遠端服務呼叫超時時間,單位:毫秒。預設為 1000 毫秒,胖友可以根據自己業務修改
    filter: -exception # 去掉 ExceptionFilter
    UserRpcService:
      version: 1.0.0
    # validation: true 開啟將驗證所有Service的引數
  scan:
    base-packages: nb.yucai.dubbo.nacosdemo.service

nacos:
  config:
    password: nacos
    username: nacos
  1. Consumer

整合過程與上述Provider完全一致。

  1. 驗證

登入Nacos控制檯即可看見。

整合Sentinel

Sentinel 是阿里中介軟體團隊開源的,面向分散式服務架構的輕量級流量控制產品,主要以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個維度來幫助使用者保護服務的穩定性。

次小節進行 Dubbo 和 Sentinel 的整合,使用 Sentinel 進行 Dubbo 的流量保護。Sentinel已經對 Dubbo 進行適配,所以我們只要引入它,基本就完成了 Dubbo 和 Sentinel 的整合,賊方便。

  1. Api

與註解配置的Api一致,無需改動

  1. Provider

引入依賴

<!-- Sentinel 核心庫 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.7.1</version>
</dependency>
<!-- Sentinel 接入控制檯 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>1.7.1</version>
</dependency>
<!-- Sentinel 對 Dubbo 的支援 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-apache-dubbo-adapter</artifactId>
    <version>1.7.1</version>
</dependency>

新建sentinel.properties

csp.sentinel.dashboard.server=127.0.0.1:7070

建立UserController類,增加呼叫UserRpcService服務的HttpAPI介面

@RestController
@RequestMapping("/user")
public class UserController {
    @Reference(version = "${dubbo.consumer.UserRpcService.version}")
    private UserRpcService userRpcService;

    @GetMapping("/get")
    public UserDTO get(@RequestParam("id") Integer id) {
        return userRpcService.get(id);
    }
}
  1. Consumer
  • 使用 ProviderApplication 啟動服務提供者。使用 ConsumerApplication 啟動服務消費者。
  • 訪問服務消費者的 http://127.0.0.1:8080/user/get?id=1 介面,保證相關資源的初始化。

下面,我們來演示使用 Sentinel 對服務消費者的流量控制。Sentinel 對服務提供者的流量控制是一樣的,胖友可以自己去嘗試。

  • 使用瀏覽器,訪問下 http://127.0.0.1:7070/ 地址,進入 Sentinel 控制檯。
    然後,點選 Sentinel 控制檯的「簇點鏈路」選單,可以看到看到 Dubbo 服務消費者產生的 nb.yucai.dubbo.apidemo.UserRpcService:get(java.lang.Integer) 資源。「新增流控規則」。填寫流控規則,如下圖所示:
  • 這裡,我們建立的是比較簡單的規則,僅允許該資源被每秒呼叫一次。
  • 使用瀏覽器,快速訪問 http://127.0.0.1:8080/user/get?id=1 介面兩次,會呼叫 UserService#get(Integer id) 方法兩次,會有一次被 Sentinel 流量控制而拒絕,返回結果如下圖所示:

因為預設的錯誤提示不是很友好,所以胖友可以自定義 SpringMVC 全域性錯誤處理器,對 Sentinel 的異常進行處理。

4. 下篇預告

  1. 新增引數驗證
  2. 自定義實現拓展點