Dubbo中文官网,大神官网镇楼!
在第一篇《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包部署
面向服务的核心是对传统的垂直架构进行改造,其中的核心技术就是分布式服务框架,应用也从集中式走向了分布式,大规模系统的架构设计原则就是尽可能的拆分,以达到更好的独立扩展与伸缩,更灵活的部署、更好的隔离和容错,更高的开发效率,具体的拆分策略是:横向拆分和纵向拆分。
在上面的拆分思路就是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文件中添加了如下的配置:
${project.build.directory}/classes/META-INF/spring
src/main/resources/spring
true
spring-context.xml
配置dubbo插件,打包jar文件时,配置manifest文件,加入lib包的jar依赖,这个引用的dubbo的Main类,所实现的main()方法源代码我在下面也贴了出来:
org.apache.maven.plugins
maven-jar-plugin
target/classes/
com.alibaba.dubbo.container.Main
false
true
lib/
.
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中加入如下:
${project.build.directory}/classes
src/main/resources
true
**/*.xml
**/*.properties
3.顺序安装依赖库
前面的步骤完成好了以后,那我们该如何去用容器化的方式启动服务呢?之前的做法是通过run我们自己写的main()方法,现在已经交给容器去做了,容器生成jar包,运行jar包来启动服务,这样是不是更简单,但是前提是要用maven来打包,而maven的打包是需要前提的。
在打开service-user的pom文件时,会有一个dependency的依赖配置项,里面反映了一个项目启动时的依赖顺序,需要的依赖项会从maven仓库中去寻找,如果之前从未构建过,那么启动的时候是会有报错的,那么就需要采用maven的install命令去构建jar包。在服务提供者的pom依赖项里我们发现了需要提前准备好的jar包,一个个来构建吧。
在intellij idea中直接打开maven的build,点击一下就能构建打包了,全都点一遍(按照依赖的先后来):
每次构建完成后是可以在maven的私有库中找到像对应的jar包的,生成以后的样子:
在最后一项中启动服务容器的时候,install以后打开target目录
可以发现所有需要的依赖的jar包已经放入了lib包中,而我们只需要执行edu-service-user.jar包就可以方便的启动服务容器了,用这个命令:
java -jar yourJarPackName.jar &
最后如果cmd没有报错,且有如下提示,恭喜,容器化启动服务的方式就算成功了!
除了在cmd窗口查看是否正常启动,在dubbo-admin管理后台同样可以查看是否正常启动:
在服务列表中有找到自己的服务名,证明启动是成功的。