Dubbo实践篇2——Dubbo+Zookeeper项目搭建(基于Linux)

Dubbo中文官网,大神官网镇楼!

《Dubbo实践篇2——Dubbo+Zookeeper项目搭建(基于Linux)》

在第一篇《Dubbo实践篇1——基于传统项目的服务化改造》还存在几个不足之处,第一,服务的提供者是通过main()方法来实现的,并不优雅;第二,服务是基于windows开发环境,实际上大多数的项目都需要基于Linux的生产环境,需要部署服务;第三、服务的模块还可以拆分的更合理,将公共层划分的更细致。

一、模块的细拆分

首先针对模块拆分不够细致的问题,在这里重新进行了划分,原来的4个子模块现在可以细分为以下8个,下面对各个模块进行详细阐述:

  • edu-common:实体类、页面模型类、异常类
  • edu-common-config:存放项目中的资源及配置文件
  • edu-common-core:数据访问层baseDao接口及实现类
  • edu-common-parent:项目总依赖,顶层pom文件
  • edu-common-web:web常量及状态码
  • edu-facade-user:业务逻辑层接口
  • edu-service-user:业务逻辑层实现类
  • edu-web-boss:controller层+web资源文件,需要war包部署

《Dubbo实践篇2——Dubbo+Zookeeper项目搭建(基于Linux)》 项目结构图

面向服务的核心是对传统的垂直架构进行改造,其中的核心技术就是分布式服务框架,应用也从集中式走向了分布式,大规模系统的架构设计原则就是尽可能的拆分,以达到更好的独立扩展与伸缩,更灵活的部署、更好的隔离和容错,更高的开发效率,具体的拆分策略是:横向拆分纵向拆分
在上面的拆分思路就是common层的抽取,MVC三层的解耦,在Model层面上继续进行细致的划分,将service和dao独立的抽取出来。

2.Dubbo服务的运行方式

Dubbo服务的运行方式主要有三种方式:

1、使用Servlet容器运行(Tomcat、Jetty等) ——不可取
缺点:增加复杂性(端口、管理)
浪费资源(内存)

2、自建Main方法类来运行( Spring容器) ——不建议(本地调试可用)
缺点: Dobbo本身提供的高级特性没用上
自已编写启动类可能会有缺陷

3、使用Dubbo框架提供的Main方法类来运行( Spring容器) —-建议使用
优点:框架本身提供( com.alibaba.dubbo.container.Main)
可实现优雅关机( ShutdownHook)

在上一篇文章的方法中,实际上是采取的第二种方法来实现的,作为本地调试是很方便的,但缺点也比较明显:没有很好的异常处理,也没有考虑关机情景,因此最好是采用第三种方法来对项目的服务启动进行改写。那第三种方法提到的优雅的关机是什么呢?

Dubbo 是通过 JDK 的 ShutdownHook 来完成优雅停机的,所以如果用户使用 kill -9 PID 等强制关闭指令,是不会执行优雅停机的,只有通过 kill PID 时,才会执行。

设置优雅停机超时时间,缺省超时时间是 10 秒,如果超时则强制关闭。

# dubbo.properties
dubbo.service.shutdown.wait=15000

如果 ShutdownHook 不能生效,可以自行调用,使用tomcat等容器部署的場景,建议通过扩展ContextListener等自行调用以下代码实现优雅停机:

ProtocolConfig.destroyAll();

OK,假设你看了以上内容都不懂,没关系,这些暂时不用理会,需要做的不是在这里,而是在服务容器的配置这一块。

2.服务容器

服务容器是一个 standalone 的启动程序,因为后台服务不需要 Tomcat 或 JBoss 等 Web 容器的功能,如果硬要用 Web 容器去加载服务提供方,增加复杂性,也浪费资源。服务容器只是一个简单的 Main 方法,并加载一个简单的 Spring 容器,用于暴露服务。既然如此我们就按照dubbo官网的推荐,通过spring容器去加载,二者个需要做到两点:

  • 1.自动加载META-INF/spring目录下的所有 Spring 配置
  • 2.配置 spring 配置加载位置:

第一点的实现在service-user的pom文件中添加了如下的配置:

<resource>
    <targetPath>${project.build.directory}/classes/META-INF/spring</targetPath>
    <directory>src/main/resources/spring</directory>
    <filtering>true</filtering>
    <includes>
        <include>spring-context.xml</include>
    </includes>
</resource>

配置dubbo插件,打包jar文件时,配置manifest文件,加入lib包的jar依赖,这个引用的dubbo的Main类,所实现的main()方法源代码我在下面也贴了出来:

<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>
            <!-- 打包时 MANIFEST.MF文件不记录的时间戳版本 -->
            <useUniqueVersions>false</useUniqueVersions>
            <addClasspath>true</addClasspath>
            <classpathPrefix>lib/</classpathPrefix>
        </manifest>
        <manifestEntries>
            <Class-Path>.</Class-Path>
        </manifestEntries>
    </archive>
</configuration>
</plugin>
<plugin>

Dubbo中main()方法的实现,考虑了各种异常,并加锁实现,比我们自己写的main() 启动方法的确优雅了许多。

public static void main(String[] args) {
        try {
            if(args == null || args.length == 0) {
                String e = ConfigUtils.getProperty("dubbo.container", loader.getDefaultExtensionName());
                args = Constants.COMMA_SPLIT_PATTERN.split(e);
            }

            final ArrayList var8 = new ArrayList();

            for(int e1 = 0; e1 < args.length; ++e1) {
                var8.add(loader.getExtension(args[e1]));
            }

            logger.info("Use container type(" + Arrays.toString(args) + ") to run dubbo serivce.");
            if("true".equals(System.getProperty("dubbo.shutdown.hook"))) {
                Runtime.getRuntime().addShutdownHook(new Thread() {
                    public void run() {
                        Iterator i$ = var8.iterator();

                        while(i$.hasNext()) {
                            Container container = (Container)i$.next();

                            try {
                                container.stop();
                                Main.logger.info("Dubbo " + container.getClass().getSimpleName() + " stopped!");
                            } catch (Throwable var6) {
                                Main.logger.error(var6.getMessage(), var6);
                            }

                            Class t = Main.class;
                            synchronized(Main.class) {
                                Main.running = false;
                                Main.class.notify();
                            }
                        }

                    }
                });
            }

            Iterator var10 = var8.iterator();

            while(var10.hasNext()) {
                Container container = (Container)var10.next();
                container.start();
                logger.info("Dubbo " + container.getClass().getSimpleName() + " started!");
            }

            System.out.println((new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]")).format(new Date()) + " Dubbo service server started!");
        } catch (RuntimeException var7) {
            var7.printStackTrace();
            logger.error(var7.getMessage(), var7);
            System.exit(1);
        }

        Class var9 = Main.class;
        synchronized(Main.class) {
            while(running) {
                try {
                    Main.class.wait();
                } catch (Throwable var5) {
                    ;
                }
            }
        }
    }

关于第二点的设置spring配置文件的依赖依旧在pom中加入如下:

<resource>
    <targetPath>${project.build.directory}/classes</targetPath>
    <directory>src/main/resources</directory>
    <filtering>true</filtering>
    <includes>
        <include>**/*.xml</include>
        <include>**/*.properties</include>
    </includes>
</resource>     

3.顺序安装依赖库

前面的步骤完成好了以后,那我们该如何去用容器化的方式启动服务呢?之前的做法是通过run我们自己写的main()方法,现在已经交给容器去做了,容器生成jar包,运行jar包来启动服务,这样是不是更简单,但是前提是要用maven来打包,而maven的打包是需要前提的。

在打开service-user的pom文件时,会有一个dependency的依赖配置项,里面反映了一个项目启动时的依赖顺序,需要的依赖项会从maven仓库中去寻找,如果之前从未构建过,那么启动的时候是会有报错的,那么就需要采用maven的install命令去构建jar包。在服务提供者的pom依赖项里我们发现了需要提前准备好的jar包,一个个来构建吧。

《Dubbo实践篇2——Dubbo+Zookeeper项目搭建(基于Linux)》 pom中的依赖项

在intellij idea中直接打开maven的build,点击一下就能构建打包了,全都点一遍(按照依赖的先后来):

《Dubbo实践篇2——Dubbo+Zookeeper项目搭建(基于Linux)》 通过maven的install命令构建依赖项

每次构建完成后是可以在maven的私有库中找到像对应的jar包的,生成以后的样子:

《Dubbo实践篇2——Dubbo+Zookeeper项目搭建(基于Linux)》 install之后的jar包存放在私有库中

在最后一项中启动服务容器的时候,install以后打开target目录

《Dubbo实践篇2——Dubbo+Zookeeper项目搭建(基于Linux)》 target目录

可以发现所有需要的依赖的jar包已经放入了lib包中,而我们只需要执行edu-service-user.jar包就可以方便的启动服务容器了,用这个命令:

java -jar yourJarPackName.jar &

最后如果cmd没有报错,且有如下提示,恭喜,容器化启动服务的方式就算成功了!

《Dubbo实践篇2——Dubbo+Zookeeper项目搭建(基于Linux)》 cmd启动成功界面

除了在cmd窗口查看是否正常启动,在dubbo-admin管理后台同样可以查看是否正常启动:

《Dubbo实践篇2——Dubbo+Zookeeper项目搭建(基于Linux)》 检查服务是否运行

在服务列表中有找到自己的服务名,证明启动是成功的。

    原文作者:YitaiCloud
    原文地址: https://www.jianshu.com/p/dff67ca3300c
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞