前言
本文主要接着 上篇 接着Dubbo學習記錄(一)zookeeper、dubbo-admin管理平臺安裝部署來基於springboot用dubbo寫了一個RPC簡單的實例:實現創建一個簡單的服務接口,然後在dubbo的服務端實現該接口並向zookeeper服務器進行註冊,客戶端向zookeeper服務器訂閱該接口並使用。同時,也介紹了一下dubbo,總結了一下spring通過xml配置使用dubbo,並收集和提供了一些相關資料方便查閱。
本文完整源碼已上傳至github:https://github.com/leon2016/dubbo-parent
Dubbo簡介
官網(中文):http://dubbo.apache.org/zh-cn/
git源碼:https://github.com/apache/incubator-dubbo.git
官方文檔:http://dubbo.apache.org/zh-cn/docs/user/quick-start.html (必讀)
dubbo-admin:https://github.com/apache/incubator-dubbo-admin/tree/master
dubbo-admin打好的war包:https://pan.baidu.com/s/1UuCWpUeTm0riumnKmKE2eg 密碼:e5ic
Dubbo是什麼
Dubbo是一個分佈式服務框架,致力於提供高性能和透明化的RPC遠程服務調用方案,以及SOA服務治理方案。簡單的說,dubbo就是個服務框架,如果沒有分佈式的需求,其實是不需要用的,只有在分佈式的時候,纔有dubbo這樣的分佈式服務框架的需求,並且本質上是個服務調用的東東,說白了就是個遠程服務調用的分佈式框架(告別Web Service模式中的WSdl,以服務者與消費者的方式在dubbo上註冊)
Dubbo能做什麼
- 遠程通訊:透明化的遠程方法調用,就像調用本地方法一樣調用遠程方法,只需簡單配置,沒有任何API侵入。
- 集羣容錯:軟負載均衡及容錯機制,可在內網替代F5等硬件負載均衡器,降低成本,減少單點。
- 自動發現:服務自動註冊與發現,不再需要寫死服務提供方地址,註冊中心基於接口名查詢服務提供者的IP地址,並且能夠平滑添加或刪除服務提供者。
特性
Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高性能、輕量級的開源Java
RPC框架,它提供了三大核心能力:面向接口的遠程方法調用,智能容錯和負載均衡,以及服務自動註冊和發現。-- 摘自官網(中文)
架構
節點角色說明
- Provider 暴露服務的服務提供方
- Consumer 調用遠程服務的服務消費方
- Registry 服務註冊與發現的註冊中心(zookeeper)
- Monitor 統計服務的調用次數和調用時間的監控中心
- Container 服務運行容器
調用關係說明
1.服務容器負責啓動,加載,運行服務提供者。
2.服務提供者在啓動時,向註冊中心註冊自己提供的服務。
3.服務消費者在啓動時,向註冊中心訂閱自己所需的服務。
4.註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連接推送變更數據給消費者。
5.服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,如果調用失敗,再選另一臺調用。
6.服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心。
Dubbo 架構具有以下幾個特點,分別是連通性、健壯性、伸縮性、以及向未來架構的升級性。
基本應用
如圖,系統A通過系統B查詢數據庫獲得數據:
更多dubbo自身技術選型及原理可參考官方文檔,很詳細的。
通過註解使用dubbo實例(springboot版)
1.創建Maven項目(分模塊)
(1)新建Maven Project : dubbo-parent (作爲父級模塊)
(2)新建Maven Module:egg-api (服務端、客戶端共享的接口模塊)
(3)同理,新建Maven Module:egg-provider(服務端)、egg-consumer(客戶端)
(4)目錄結構
下面是我的項目最終目錄結構:
2.配置依賴(pom.xml)
dubbo-parent/pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.leon</groupId>
<artifactId>dubbo-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>egg-api</module>
<module>egg-provider</module>
<module>egg-consumer</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<curator-framework.version>4.0.1</curator-framework.version>
<zookeeper.version>3.4.13</zookeeper.version>
<dubbo.starter.version>0.2.0</dubbo.starter.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${dubbo.starter.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>${curator-framework.version}</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
egg-api/pom.xml:
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.leon</groupId>
<artifactId>dubbo-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>egg-api</artifactId>
<name>egg-api</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
egg-provider/pom.xml:
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.leon</groupId>
<artifactId>dubbo-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>egg-provider</artifactId>
<name>egg-provider</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>com.leon</groupId>
<artifactId>egg-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
dubbo-consumer/pom.xml:
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.leon</groupId>
<artifactId>dubbo-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>egg-consumer</artifactId>
<name>egg-consumer</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.leon</groupId>
<artifactId>egg-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置完pom.xml,更新一下maven項目:右鍵dubbo-parent>maven->update project…
3.配置dubbo屬性(application.properties)
(1)服務提供方(服務端)dubbo配置
新建/egg-provider/src/main/resources/application.properties:
#服務器端口配置
spring.application.name = dubbo-provider
server.port = 9090
#提供方應用名稱,用於計算依賴關係(同樣的服務名字相同,不要和別的服務同名,下面這4個個結合@service註解是dubbo核心配置)
dubbo.application.name = dubbo-provider
#指定註冊中心的位置,使用zookeeper註冊中心暴露服務地址
dubbo.registry.address = zookeeper://localhost:2181
#用dubbo協議在20880端口暴露服務
dubbo.protocol.name = dubbo
dubbo.protocol.port = 20880
#統一設置服務提供方的規則
dubbo.provider.timeout = 2000
#服務提供方版本號
demo.service.version = 1.0.0
(2)服務消費方(客戶端)dubbo配置
新建/egg-consumer/src/main/resources/application.properties:
#服務器端口配置
spring.application.name = dubbo-consumer
server.port = 9091
#服務消費方方應用名稱,用於計算依賴關係(同樣的服務名字相同,不要和別的服務同名,下面這4個個結合@service註解是dubbo核心配置)
dubbo.application.name = egg-consumer
#指定註冊中心的位置,使用zookeeper註冊中心暴露服務地址
dubbo.registry.address = zookeeper://localhost:2181
#用dubbo協議在20880端口暴露服務
dubbo.protocol.name = dubbo
dubbo.protocol.port = 20880
#統一設置服務消費方的規則
dubbo.provider.timeout = 2000
#調用的服務提供方的版本號
demo.service.version = 1.0.0
4.定義服務接口
新建/egg-api/src/main/java/com/leon/api/service/IHelloworldService.java:
package com.leon.api.service;
/**
* API接口
*
* @author leon
*
*/
public interface IHelloworldService {
String dubbo();
}
5.服務端實現接口
新建/egg-provider/src/main/java/com/leon/provider/service/impl/HelloworldImpl.java:
package com.leon.provider.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.leon.api.service.IHelloworldService;
/**
* 服務提供方實現API接口
*
* 註解"@service" 聲明需要暴露的服務接口
*
*
* @author leon
*
*/
@Service(version = "${demo.service.version}")
public class HelloworldImpl implements IHelloworldService {
@Override
public String dubbo() {
return "hello world!";
}
}
爲了springboot方式啓動服務端,新建一個啓動類
/egg-provider/src/main/java/com/leon/provider/EggProviderApplication.java:
package com.leon.provider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
/**
* 服務提供啓動類
*
* "@EnableDubbo"開啓dubbo支持
*
* @author leon
*
*/
@EnableDubbo
@SpringBootApplication
public class EggProviderApplication {
public static void main(String[] args) {
SpringApplication.run(EggProviderApplication.class, args);
}
}
6.客戶端引用接口
新建/egg-consumer/src/main/java/com/leon/consumer/controller/ConsumerController.java:
package com.leon.consumer.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.dubbo.config.annotation.Reference;
import com.leon.api.service.IHelloworldService;
/**
* 服務消費方
*
* 註解"@Reference(version = "${demo.service.version}")"引用服務方提供的接口
*
* @author leon
*/
@RestController
public class ConsumerController {
@Reference(version = "${demo.service.version}")
private IHelloworldService helloWorld;
@RequestMapping("/dubbo/helloWorld")
public String helloWorld() {
return helloWorld.dubbo();
}
}
爲了springboot方式啓動客戶端,新建一個啓動類
/egg-consumer/src/main/java/com/leon/consumer/EggConsumerApplication.java:
package com.leon.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
/**
* 服務消費方啓動類
*
* "@EnableDubbo"開啓dubbo支持
*
* @author leon
*
*/
@EnableDubbo
@SpringBootApplication
public class EggConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EggConsumerApplication.class, args);
}
}
7.啓動項目
(1)先啓動服務端:右鍵EggProviderApplication.java執行main函數
(2)再啓動客戶端:右鍵EggConsumerApplication.java執行main函數
(3)訪問:http://localhost:9091/dubbo/helloWorld/
打印:hello world !代表egg-consumer成功調用egg-consumer的HelloWorldImpl.dubbo()
(4)訪問dubbo-admin:http://localhost:8080/dubbo-admin-2.6.0/
home頁紅框 stat顯示了當前服務方與消費方狀態:
點擊services可以看到所有註冊的接口:
點擊接口可以查看詳情:
8.源碼
本文完整源碼已上傳
至github:https://github.com/leon2016/dubbo-parent
參考文獻
https://www.cnblogs.com/gengaixue/p/8976891.html
後記
一波走下來,發現dubbo真的很優秀,學習曲線也還比較平滑。
by the way, 要在spring中通過xml配置使用dubbo的話,
可以參考官方文檔
http://dubbo.apache.org/zh-cn/docs/user/quick-start.html
和
https://blog.csdn.net/smilefyx/article/details/71024394
XML方式使用dubbo核心配置如下: