13、Spring技术栈-整合dubbo、zookeeper实现高可用分布式微服务实战

Spring技术栈-整合dubbo、zookeeper一文中我们已经讲述了如何整合Spring、dubbo、zookeeper来开发一个分布式的应用。本文在上文的基础上来描述如何打包部署dubbo微服务,实现一个高可用的微服务集群,如果不知道如何整合Spring、dubbo、zookeeper,请读者先阅读上文,然后再阅读此文进行微服务的打包和部署操作。

准备工作

我们假设读者已经在自己的环境中安装了maven,java jdk等必须的基础软件,本文不会讲述如何安装这些基础构件,只描述部署dubbo微服务的打包、部署、运行测试方案。

安装虚拟机3台,笔者安装虚拟机使用的是VirtualBox,读者可根据自己的环境具体分析,安装完成虚拟机之后,要确保虚拟机和宿主机之间能够进行网络通讯。

IP备注开放端口
192.168.199.177(宿主机)MySQL是安装在宿主机3306(需要添加入站规则,将3306端口开放,否则虚拟机无法链接MySQL)
192.168.199.161(虚拟机)zookeeper注册中心2181
192.168.199.249(虚拟机)服务主机20882
192.168.199.126(虚拟机)服务主机20882

以上是笔者机器上所安装的虚拟机信息,仅供参考,读者可根据自己的具体环境具体安装。

实例介绍

我们以开发一个博客服务为例,用户在访问博客列表时,我们一开始启动两个服务实例注册到Zookeeper,然后让其中一个服务宕机,然后测试博客列表是否能够正常访问。

服务接口

public interface BlogFacade {
    /**
     * @Comment 获取博客列表
     * @Author Ron
     * @Date 2017年10月25日 下午2:53:39
     * @return
     */
    List<BlogContent> findBlogList(BlogContent blogContent);

    /**
     * @Comment 获取博客内容
     * @Author Ron
     * @Date 2017年10月25日 下午3:04:57
     * @return
     */
    BlogContent getBlog(String bid);
}

服务实现

新建一个blog_service项目,新建BlogService实现以上接口

@Component("blogService")
public class BlogService implements BlogFacade{

    private Logger logger = LogManager.getLogger(this.getClass());

    @Autowired 
    private BlogContentMapper blogContentMapper;

    @Autowired  
    RedisUtils redisUtils;  

    /**
     * @Comment 获得博客列表
     * @Author Ron
     * @Date 2017年10月25日 下午3:04:01
     * @return
     */
    @Override
    public List<BlogContent> findBlogList(BlogContent blogContent) {
        logger.info("进入博客查询列表");
        try {
            return blogContentMapper.selectList(blogContent);
        } catch (Exception e) {
            logger.error("访问博客列表失败"+e);
            return null;
        }
    }

    /**
     * @Comment 获取博客内容
     * @Author Ron
     * @Date 2017年10月25日 下午3:05:27
     * @return
     */
    @Override
    public BlogContent getBlog(String bid) {
        if(redisUtils.exists(bid)){
            logger.info("缓存命中博客"+bid);
            return (BlogContent) redisUtils.get(bid);
        }else{
            logger.info("缓存尚未命中博客"+bid);
            BlogContent blogContent = blogContentMapper.selectByPrimaryKey(bid);
            redisUtils.set(bid, blogContent);
            return blogContent;
        }
    }
}

在服务实例中我们用到了Redis做缓存,读者可参考12、Spring技术栈-Redis Sentinel实战一文了解如何使用Redis实现缓存集群。

其中blogContentMapper是通过整合Mybatis访问MySQL的映射类,关于如何整合Mybatis,读者可参考2、Spring技术栈-整合Mybatis

Dubbo 服务提供方配置

在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="ron-service-blog" logger="log4j"/>

    <dubbo:registry protocol="zookeeper" address="${registry.address}"/>   

    <dubbo:monitor protocol="registry"/>

    <dubbo:protocol name="dubbo" port="${service.port}" serialization="java" />

    <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.blog.BlogFacade" ref="blogService" />
</beans>

config.properties配置

在配置文件中,增加zookeeper地址和端口以及服务端口的配置。

#zookeeper配置
registry.address=192.168.199.161:2181
service.port=20882

微服务项目pom.xml配置

在服务的pom.xml文件中除了添加dubbo和zookeeper客户端的依赖之外,我们还需要添加一些maven插件,帮助我们在使用maven打包项目时能够拷贝依赖的jar包和相关的资源文件到指定的目录。同时因为我们开发的微服务一般情况家都是一个jar包,所以我们需要这个jar包能够单据运行,所以我们也需要在pom文件中指定main函数(程序入口)的位置。具体的配置如下:

dubbo_version:2.8.4a
zkclient_version:0.10

    <!-- 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>
    <build>
        <finalName>ron-service-blog</finalName>
        <resources>
            <!-- 资源文件 -->
            <resource>
                <targetPath>${project.build.directory}/classes</targetPath>
                <directory>src/main/java</directory>
                <filtering>true</filtering>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <!--配置文件拷贝的对象目录 -->
                <targetPath>${project.build.directory}/classes</targetPath>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
            </resource>
            <resource>
                <!--配置文件必须放在spring文件夹下,否则dubbo即使显示启动成功,实际上也没有启动成功 -->
                <targetPath>${project.build.directory}/classes/META-INF/spring</targetPath>
                <directory>src/main/resources/</directory>
                <filtering>true</filtering>
                <includes>
                    <include>spring-context.xml</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <classesDirectory>target/classes/</classesDirectory>
                    <archive>
                        <manifest>
                            <mainClass>com.alibaba.dubbo.container.Main</mainClass>
                            <useUniqueVersions>false</useUniqueVersions>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                        </manifest>
                        <manifestEntries>
                            <Class-Path>.</Class-Path>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <type>jar</type>
                            <includeTypes>jar</includeTypes>
                            <outputDirectory>
                                ${project.build.directory}/lib
                            </outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

Dubbo消费者配置

在web端的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: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="blog-service" />

    <context:property-placeholder ignore-unresolvable="true" location="classpath:config.properties" />

    <!-- 使用zookeeper注册中心暴露服务地址 -->
    <dubbo:registry protocol="zookeeper" address="${registry.address}" />

    <dubbo:consumer check="false" />

    <!-- 服务应用 -->
    <dubbo:reference id="blogService"  interface="ron.blog.blog_facade.blog.BlogFacade" />
</beans>

其中配置参数都添加到config.properties中,内容如下

#zookeeper配置
registry.address=192.168.199.161:2181

打包blog_service微服务

在命令行工具中,进入项目pom.xml文件目录,执行以下命令进行打包

mvn clean
mvn package -Dmaven.test.skip=true

等待打包完成之后,我们在项目的target目录先会看到一个*.jar包和一个lib文件夹,部署时只需要上传jar包和lib文件夹即可。

这里写图片描述

安装和配置zookeeper

安装zookeeper作为服务的注册中心,本文将zookeeper安装在192.168.199.161这台虚拟机上,zookeeper安装参见Zookeeper精要-standalone模式,本文主要描述的是服务的高可用,注册中心我们采用单点即可。

注意:服务所指定的注册中心的地址和端口必须是您所安装的zookeeper所在的虚拟机地址和端口。

#zookeeper配置
registry.address=192.168.199.161:2181
#服务端口
service.port=20882

部署服务

我们假设读者已经在自己的虚拟机上安装了java环境,所以这里就不说明如何安装java环境。

在服务主机(笔者的服务主机是192.168.199.126、192.168.199.249)新建一个目录,用于存放服务相关文件。

mkdir /data/blogSrv

通过ftp工具将打包好的内容上传到该目录,笔者使用的是filezilla.exe。文件上传完成之后,编写启动脚本。

新建start.sh,文件,写入启动脚本。

cd /data/blogSrv
vi start.sh

在start.sh中写入如下内容

#!/bin/bash
nohup java -jar ron-service-blog.jar > nohup.log 2>&1 &

解释一下启动脚本命令的含义:在后台运行服务并将服务的错误流信息作为标准输出流输出到nohup.log文件中。

赋予start.sh脚本读写权限

chmod 777 start.sh

启动服务

在服务主机上使用如下命令分别执行启动脚本启动服务。

cd /data/blogSrv
./start.sh

服务启动成功后,可通过如下命令查看是否启动成功

ps -ef|grep ron-service-blog(这里是jar包的名称)

如果启动成功,您会看到如下内容

[root@localhost blogSrv]# ps -ef|grep ron-service-blog
root      4193     1  0 14:09 pts/0    00:00:29 java -jar ron-service-blog.jar
root      4348  2316  0 15:25 pts/0    00:00:00 grep --color=auto ron-service-blog

如果启动失败,在服务jar包存放的目录会生成一个nohup.log文件,读者可查看该日志文件中的内容查看错误信息并修复。

服务可用性测试

如果两台机器上的服务都成功启动,我们就可以打开我们的服务消费端,亲测博客页面能访问。
这里写图片描述

接下来我们去到任意一台部署服务的虚拟机,使用kill命令杀掉服务进程,再次刷新页面,博客列表页面依然可用。

这里写图片描述

重新刷新页面

这里写图片描述

系统源码:http://download.csdn.net/download/zyhlwzy/10122870

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RonTech

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值