Dubbo 01 基礎概念與入門工程搭建
Dubbo 01 基礎概念與入門工程搭建
1. 概述基本概念
定義
Apache Dubbo |ˈdʌbəʊ| 是一款高效能、輕量級的開源 Java RPC 框架,它提供了三大核心能力:
- 面向介面的遠端方法呼叫
- 智慧容錯和負載均衡
- 以及服務自動註冊和發現。
架構
角色
- Registry 註冊中心,用於服務的註冊與發現。
- Provider 服務提供者,通過向 Registry 註冊服務。
- Consumer 服務消費者,通過從 Registry 發現服務。後續直接呼叫 Provider ,無需經過 Registry 。
- Monitor 監控中心,統計服務的呼叫次數和呼叫時間。
- Container 服務執行容器。
呼叫關係
- 服務容器負責啟動,載入,執行服務提供者。
- 服務提供者在啟動時,向註冊中心註冊自己提供的服務。
- 服務消費者在啟動時,向註冊中心訂閱自己所需的服務。
- 註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連線推送變更資料給消費者。
- 服務消費者,從提供者地址列表中,基於軟負載均衡演算法,選一臺提供者進行呼叫,如果呼叫失敗,再選另一臺呼叫。
- 服務消費者和提供者,在記憶體中累計呼叫次數和呼叫時間,定時每分鐘傳送一次統計資料到監控中心。
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 介面,提供給消費者使用。
- 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;
}
}
- 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
- 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>
- 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的引數
- 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);
}
}
- 新建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>
- 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
- 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>
- 配置檔案
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
- 配置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>
- 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
- 引入依賴
基本與XML方式實現一致,可參考上文
- 應用配置檔案
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檔案進行配置
- 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 - 女
}
}
- ProviderApplication
正常建立即可,無需新增@ImportResource註解,引入dubbo.xml即可
Consumer
- 引入依賴
基本與XML方式實現一致,可參考上文
- 應用配置檔案
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
- 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 的整合,賊方便。
-
Nacos官網下載,執行即可。
-
API
以上文註解式配置的方法為例,仍採用上述Service,無需改動
- 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
- Consumer
整合過程與上述Provider完全一致。
- 驗證
登入Nacos控制檯即可看見。
整合Sentinel
Sentinel 是阿里中介軟體團隊開源的,面向分散式服務架構的輕量級流量控制產品,主要以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個維度來幫助使用者保護服務的穩定性。
次小節進行 Dubbo 和 Sentinel 的整合,使用 Sentinel 進行 Dubbo 的流量保護。Sentinel已經對 Dubbo 進行適配,所以我們只要引入它,基本就完成了 Dubbo 和 Sentinel 的整合,賊方便。
- Api
與註解配置的Api一致,無需改動
- 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);
}
}
- 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. 下篇預告
- 新增引數驗證
- 自定義實現拓展點