在我们的Spring Web开发实战的前8篇文章中,我们详细介绍了使用Spring从0开始搭建一个项目并整合log4j2、整合MyBatis,使用hibernate-validator进行服务端数据验证、使用Spring Session管理服务端会话以及过滤器、拦截器的使用。通过前面的文章我们大致可以完成一个简单系统的实现。但是出于学习的目的,我们需要不停的完善系统,不停的学习新的东西以充实自己。此文我们将介绍如何整合Spring、dubbo、zookeeper进行分布式系统的开发。
关于分布式系统的设计概念,可参考分布式系统设计理念。
1、zookeeper的安装与介绍
关于zookeeper,我们已经有一些列的文章对其进行介绍,zookeeper请直接参考Zookeeper系列,但是在我们的开发环境中(windows),我们需要下载zookeeper包,解压并点击bin目录下的zkServer.cmd即可在本地windows环境运行。
zookeeper默认端口号为2181,但是读者可以自行进行个性化配置,配置文件在conf目录下,具体参数的解释以及如何配置,也可参考Zookeeper系列。
2、Spring整合dubbo、zookeeper
首先我们现在父级项目的pom.xml文件中先定义我们需要整合的dubbo、zookeeper的版本(可直接到GitHub下载源码)。
<dubbo_version>2.5.5</dubbo_version>
<zkclient_version>0.10</zkclient_version>
2.1. 开发服务提供方
我们以用户服务为例来阐述服务提供方的开发过程。
首先,使用dubbo,我们需要为每一个服务提供一个接口,服务的消费方通过该接口调用服务。以用户服务为例,我们需要新建一个UserBaseFacade接口,这个接口服务的消费方和服务的提供方公用。
public interface UserBaseFacade {
/**
* @Comment 检查邮箱是否存在
* @Author Ron
* @Date 2017年8月31日 下午5:18:09
* @return
*/
boolean checkEmail(String email);
}
1、新建一个blog_user_service模块,新建方式请参考Spring技术栈-博客系统基础架构。
2、该模块依赖blog_dao(数据库交互)、blog_facade(接口模块)、dubbo、zkclient;
pom.xml配置如下:
<!--依赖blog-dao模块 -->
<dependency>
<groupId>ron.blog</groupId>
<artifactId>blog_dao</artifactId>
<version>${project.version}</version>
</dependency>
<!--依赖blog-facade模块 -->
<dependency>
<groupId>ron.blog</groupId>
<artifactId>blog_facade</artifactId>
<version>${project.version}</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo_version}</version>
</dependency>
<!-- zookeeper -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>${zkclient_version}</version>
</dependency>
3、开发并配置服务
新建服务实现类UserBaseService并实现UserBaseFacade接口;
/**
* @Comment 用户服务,必须指定服务名称
* @Author Ron
* @Date 2017年9月26日 下午3:45:54
* @return
*/
@Component("userService")
public class UserBaseService implements UserBaseFacade {
private Logger logger = LogManager.getLogger(this.getClass());
@Autowired
BlogUserBaseDao blogUserBaseDao;
/**
* @Comment 检查邮箱是否存在
* @Author Ron
* @Date 2017年8月31日 下午5:18:28
* @return
*/
@Override
public boolean checkEmail(String email) {
if (blogUserBaseDao.checkEmail(email) > 0) {
return true;
}
return false;
}
}
在config.properties文件中增加zookeeper地址的配置:
#zookeeper配置
registry.address=127.0.0.1:2181
在resources目录新建dubbo/dubbo.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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="blog-user-service" logger="log4j"/>
<dubbo:registry protocol="zookeeper" address="${registry.address}"/>
<dubbo:monitor protocol="registry"></dubbo:monitor>
<dubbo:protocol name="dubbo" port="20881" />
<dubbo:provider timeout="30000" loadbalance="random" >
<dubbo:parameter key="shutdown.timeout" value="60000" />
<dubbo:parameter key="shutdown.hook" value="true" />
<dubbo:parameter key="retries" value="0" />
</dubbo:provider>
<!-- 声明需要暴露的服务 -->
<dubbo:service interface="ron.blog.blog_facade.user.UserBaseFacade" ref="userService"/>
</beans>
在spring-context.xml文件中导入dubbo.xml配置
<import resource="classpath:dubbo/dubbo.xml" />
4、启动服务
新建一个服务启动器,我们这里新建一个类UserServiceProvider,通过这个类加载Spring配置文件并启动服务:
public class UserServiceProvider{
private static final Logger LOG = LogManager.getLogger(UserServiceProvider.class);
public static final String DUBBO_PROVIDER = "classpath:spring-context.xml";
private static void init() {
LOG.info("开始启动dubo服务,载入的配置服务提供文件为[" + DUBBO_PROVIDER + "]");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(DUBBO_PROVIDER);
context.registerShutdownHook();
context.start();
LOG.info("【tfs-service-user】启动完毕!");
}
public static void main(String[] args) {
init();
while (true) {
try {
Thread.currentThread();
Thread.sleep(3L);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
至此,服务提供方开发完毕。
2.2. 修改blog_pc作为服务消费方
服务消费方,需要配置blog_facade、dubbo和zookeeper的依赖
<!-- 添加对Facade的依赖 -->
<dependency>
<groupId>ron.blog</groupId>
<artifactId>blog_facade</artifactId>
<version>${project.version}</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo_version}</version>
</dependency>
<!-- zookeeper -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>${zkclient_version}</version>
</dependency>
依赖配置完成之后,在resources目录下新建dubbo目录,在dubbo目录下新建dubbo_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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="ron_blog_consumer" />
<context:property-placeholder ignore-unresolvable="true" location="classpath:config.properties" />
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry protocol="zookeeper" address="${registry.address}" />
<!-- 用户相关服务 -->
<dubbo:reference id="userService" interface="ron.blog.blog_facade.user.UserBaseFacade" />
</beans>
在spring-context.xml文件中导入服务消费配置文件:
<!-- 导入dubbo消费者配置 -->
<import resource="classpath:dubbo/dubbo_consumer.xml" />
Ok,所有准备工作已经完成,如何运行该应用呢?
- 启动zookeeper
- 启动Redis(我们使用了Spring Session with Redis,Session都保存在了Redis中)
- 运行UserServiceProvider启动服务
- 运行blog_pc启动网站
如果运行成功,那么祝贺您,您已经启动了您的第一个分布式应用。