
前言
Dubbo是一個(gè)遠(yuǎn)程調(diào)用框架,我們要使用Dubbo的話必須要搭建一套注冊中心,Dubbo支持的注冊中心非常多,它支持Multicast、Zookeeper、Nacos、Redis和Simple作為注冊中心,而Dubbo他推薦使用Zookeeper作為它的注冊中心。
Dubbo 社區(qū)目前主力維護(hù)的有 2.6.x 和 2.7.x 兩大版本,其中2.6.x仍然放在Alibaba Group中,而2.7.x已經(jīng)放在了Apache Group中了。
本文記錄了我搭建一套Dubbo測試環(huán)境的過程,其中我搭建了Zookeeper、Dubbo-admin兩個(gè)服務(wù),然后創(chuàng)建了一個(gè)用戶服務(wù)和一個(gè)管理服務(wù),管理服務(wù)作為消費(fèi)者去調(diào)用用戶服務(wù)中的方法。
搭建Zookeeper
為了最大化簡便的把環(huán)境搭建好,我這里使用了Docker啟動(dòng)了一個(gè)Zookeeper容器。
docker run -tid --name dev-zookeeper -p 2181:2181 zookeeper
搭建Dubbo-admin
1、下載源碼
git clone https://github.com/apache/dubbo-admin.git
項(xiàng)目是一個(gè)前后端分離的項(xiàng)目,其中:
-
dubbo-admin-ui:使用vue開發(fā)的前端項(xiàng)目 -
dubbo-admin-server:使用springboot開發(fā)的主項(xiàng)目
2、修改注冊中心地址
需要確定 dubbo-admin/dubbo-admin-server/src/main/resources/application.properties 文件中。
Dubbo 2.6版本所有數(shù)據(jù)都存在注冊中心上,Dubbo 2.7版本分成了注冊中心,配置中心,和元數(shù)據(jù)中心。
本記錄中我使用的是Dubbo 2.7。
# 注冊中心地址
admin.registry.address=zookeeper://127.0.0.1:2181
# 配置中心地址
admin.config-center=zookeeper://127.0.0.1:2181
# 元數(shù)據(jù)暴露地址
admin.metadata-report.address=zookeeper://127.0.0.1:2181
3、打包啟動(dòng)
dubbo-admin是一個(gè)標(biāo)準(zhǔn)的前后端分離項(xiàng)目,部署方式有許多中,我這里使用比較簡單的方法,將前端打包,再放到后端項(xiàng)目中一起打包了。
# 進(jìn)入dubbo-admin-ui 打包前端
? ? cd dubbo-admin-ui
# 安裝依賴庫
? ? npm install
? ? npm run build
? ? cp -r target/dist/* ../dubbo-admin-server/src/main/resources/static/
? ? cd ../dubbo-admin-server
? ? mvn clean package
? ? java -jar target/dubbo-admin-server-0.2.0-SNAPSHOT.jar

編寫Demo
Dubbo 官方建議將服務(wù)接口,服務(wù)模型,服務(wù)異常等均放在 API 包中,因?yàn)榉?wù)模型及異常也是 API 的一部分,同時(shí),這樣做也符合分包原則:重用發(fā)布等價(jià)原則(REP),共同重用原則(CRP)。
如果需要,也可以考慮在 API 包中放置一份 spring 的引用配置,這樣使用方,只需在 spring 加載過程中引用此配置即可,配置建議放在模塊的包目錄下,以免沖突,
服務(wù)接口盡可能大粒度,每個(gè)服務(wù)方法應(yīng)代表一個(gè)功能,而不是某功能的一個(gè)步驟,否則將面臨分布式事務(wù)問題,Dubbo 暫未提供分布式事務(wù)支持。
服務(wù)接口建議以業(yè)務(wù)場景為單位劃分,并對(duì)相近業(yè)務(wù)做抽象,防止接口數(shù)量爆炸。不建議使用過于抽象的通用接口,如:Map query(Map),這樣的接口沒有明確語義,會(huì)給后期維護(hù)帶來不便。
common-api
common-api是定義的接口包。
├── common-api
│ ├── pom.xml
│ └── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── martain
│ │ │ └── study
│ │ │ ├── IAdminService.java
│ │ │ ├── IUserService.java
│ │ │ └── vo
│ │ │ └── UserVO.java
UserVO.java
@Data
public class UserVO implements Serializable {
private String id;
private String userName;
private Integer age;
private String email;
}
IUserService.java
public interface IUserService {
UserVO getUserById(String userId);
}
IAdminService.java
public interface IAdminService {
UserVO findUserById(String userId);
}
spring-provider-user
服務(wù)提供者需要實(shí)現(xiàn)接口的方法,并將服務(wù)注冊到注冊中心去。
└── spring-provider-user
├── pom.xml
├── spring-provider-user.iml
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── martain
│ │ └── study
│ │ ├── Application.java
│ │ └── service
│ │ └── UserService.java
│ └── resources
│ └── provider.xml
pom.xml
這里使用的是Dubbo 2.7.x ,如果使用Dubbo 2.6.x的話會(huì)有些不同。
<dependencies>
<!-- 引入接口包 -->
<dependency>
<groupId>com.martain.study</groupId>
<artifactId>common-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 引入dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.3</version>
</dependency>
<!--zookeeper 注冊中心客戶端引入 使用的是curator客戶端 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>2.7.4.1</version>
<type>pom</type>
</dependency>
</dependencies>
UserService.java
IUserService的接口實(shí)現(xiàn)類。
public class UserService implements IUserService {
public UserVO getUserById(String userId) {
UserVO userVO = new UserVO();
userVO.setId(userId);
userVO.setUserName("user-"+userId);
userVO.setAge(18);
userVO.setEmail(userId+"@qq.com");
return userVO;
}
}
provider.xml
這里需要配置dubbo相關(guān)的信息,以便于將接口暴露出去。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
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
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
">
<!-- 1、指定當(dāng)前服務(wù)/應(yīng)用的名字(同樣的服務(wù)名字相同,不要和別的服務(wù)同名) -->
<dubbo:application name="user-provider-service"></dubbo:application>
<!-- 2、指定注冊中心的位置 -->
<!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry>
<!-- 3、指定通信規(guī)則(通信協(xié)議?通信端口) -->
<dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
<!-- 4、暴露服務(wù) ref:指向服務(wù)的真正的實(shí)現(xiàn)對(duì)象 -->
<dubbo:service interface="com.martain.study.IUserService" ref="userServiceImpl" >
<dubbo:method name="getUserById" timeout="3000"></dubbo:method>
</dubbo:service>
<!-- 服務(wù)的實(shí)現(xiàn) -->
<bean id="userServiceImpl" class="com.martain.study.service.UserService"></bean>
</beans>
Application.java
public class Application {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("provider.xml");
ioc.start();
System.in.read();
}
}
啟動(dòng)

當(dāng) spring-provider-user 啟動(dòng)后,我們可以在dubbo-admin中看到服務(wù)已經(jīng)注冊進(jìn)來了。
spring-consumer-admin
├── spring-consumer-admin
│ ├── pom.xml
│ ├── spring-consumer-admin.iml
│ └── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── martain
│ │ │ └── study
│ │ │ ├── Application.java
│ │ │ └── service
│ │ │ └── AdminService.java
│ │ └── resources
│ │ └── consumer.xml
pom.xml
<dependencies>
<dependency>
<groupId>com.martain.study</groupId>
<artifactId>common-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 引入dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.3</version>
</dependency>
<!--zookeeper 注冊中心客戶端引入 使用的是curator客戶端 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>2.7.4.1</version>
<type>pom</type>
</dependency>
</dependencies>
AdminService.java
IAdminService的實(shí)現(xiàn)類
@Service
public class AdminService implements IAdminService {
@Autowired
IUserService userService;
public UserVO findUserById(String userId) {
UserVO userVO = userService.getUserById(userId);
System.out.println(userVO);
return userVO;
}
}
consumer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 配置掃描包,才能使adminService被掃描到 -->
<context:component-scan base-package="com.martain.study.service">
</context:component-scan>
<!-- 應(yīng)用名 -->
<dubbo:application name="admin-service-consumer"></dubbo:application>
<!-- 指定注冊中心地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
<!-- 生成遠(yuǎn)程服務(wù)代理,可以和本地bean一樣使用IUserService -->
<dubbo:reference interface="com.martain.study.IUserService" id="userService" >
</dubbo:reference>
</beans>
Application.java
啟動(dòng)類中,先加載了配置文件,然后再使用
IAdminServiceq去調(diào)用IUserService中的接口。
public class Application {
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("consumer.xml");
IAdminService adminService = applicationContext.getBean(IAdminService.class);
adminService.findUserById("10086");
System.out.println("調(diào)用完成....");
System.in.read();
}
}
啟動(dòng)
UserVO(id=10086, userName=user-10086, age=18, email=10086@qq.com)
調(diào)用完成....
調(diào)用成功