前言
Dubbo是一个远程调用框架,我们要使用Dubbo的话必须要搭建一套注册中心,Dubbo支持的注册中心非常多,它支持Multicast
、Zookeeper
、Nacos
、Redis
和Simple
作为注册中心,而Dubbo他推荐使用Zookeeper作为它的注册中心。
Dubbo 社区目前主力维护的有 2.6.x 和 2.7.x 两大版本,其中2.6.x仍然放在Alibaba Group中,而2.7.x已经放在了Apache Group中了。
本文记录了我搭建一套Dubbo测试环境的过程,其中我搭建了Zookeeper、Dubbo-admin两个服务,然后创建了一个用户服务和一个管理服务,管理服务作为消费者去调用用户服务中的方法。
搭建Zookeeper
为了最大化简便的把环境搭建好,我这里使用了Docker启动了一个Zookeeper容器。
docker run -tid --name dev-zookeeper -p 2181:2181 zookeeper
搭建Dubbo-admin
1、下载源码
git clone https://github.com/apache/dubbo-admin.git
项目是一个前后端分离的项目,其中:
-
dubbo-admin-ui
:使用vue开发的前端项目 -
dubbo-admin-server
:使用springboot开发的主项目
2、修改注册中心地址
需要确定 dubbo-admin/dubbo-admin-server/src/main/resources/application.properties 文件中。
Dubbo 2.6版本所有数据都存在注册中心上,Dubbo 2.7版本分成了注册中心,配置中心,和元数据中心。
本记录中我使用的是Dubbo 2.7。
# 注册中心地址
admin.registry.address=zookeeper://127.0.0.1:2181
# 配置中心地址
admin.config-center=zookeeper://127.0.0.1:2181
# 元数据暴露地址
admin.metadata-report.address=zookeeper://127.0.0.1:2181
3、打包启动
dubbo-admin是一个标准的前后端分离项目,部署方式有许多中,我这里使用比较简单的方法,将前端打包,再放到后端项目中一起打包了。
# 进入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 官方建议将服务接口,服务模型,服务异常等均放在 API 包中,因为服务模型及异常也是 API 的一部分,同时,这样做也符合分包原则:重用发布等价原则(REP),共同重用原则(CRP)。
如果需要,也可以考虑在 API 包中放置一份 spring 的引用配置,这样使用方,只需在 spring 加载过程中引用此配置即可,配置建议放在模块的包目录下,以免冲突,
服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某功能的一个步骤,否则将面临分布式事务问题,Dubbo 暂未提供分布式事务支持。
服务接口建议以业务场景为单位划分,并对相近业务做抽象,防止接口数量爆炸。不建议使用过于抽象的通用接口,如:Map query(Map),这样的接口没有明确语义,会给后期维护带来不便。
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
服务提供者需要实现接口的方法,并将服务注册到注册中心去。
└── 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的话会有些不同。
<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
的接口实现类。
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相关的信息,以便于将接口暴露出去。
<?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、指定当前服务/应用的名字(同样的服务名字相同,不要和别的服务同名) -->
<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、指定通信规则(通信协议?通信端口) -->
<dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
<!-- 4、暴露服务 ref:指向服务的真正的实现对象 -->
<dubbo:service interface="com.martain.study.IUserService" ref="userServiceImpl" >
<dubbo:method name="getUserById" timeout="3000"></dubbo:method>
</dubbo:service>
<!-- 服务的实现 -->
<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();
}
}
启动
当 spring-provider-user 启动后,我们可以在dubbo-admin中看到服务已经注册进来了。
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
的实现类
@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>
<!-- 应用名 -->
<dubbo:application name="admin-service-consumer"></dubbo:application>
<!-- 指定注册中心地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
<!-- 生成远程服务代理,可以和本地bean一样使用IUserService -->
<dubbo:reference interface="com.martain.study.IUserService" id="userService" >
</dubbo:reference>
</beans>
Application.java
启动类中,先加载了配置文件,然后再使用
IAdminServiceq
去调用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("调用完成....");
System.in.read();
}
}
启动
UserVO(id=10086, userName=user-10086, age=18, email=10086@qq.com)
调用完成....
调用成功