您的位置:首页 > 大数据 > 人工智能

dubbo源码深度解读三之container模块

2017-07-30 12:09 453 查看
前言:container为服务容器,用于部署运行服务,是一个Standlone的容器,以简单的Main加载Spring启动,因为服务通常不需要Tomcat/JBoss等Web容器的特性,没必要用Web容器去加载服务。

一,Container接口

这是一个基类的接口,这这个模块中,他的实现类有SpringContainer、Log4jContainer、JettyContainer、LogbackContainer。

看下源码:

@SPI("spring")
public interface Container {

/**
* start.
*/
void start();

/**
* stop.
*/
void stop();

}


可以发现,它有一个SPI注解,这个在common模块中已经说明了,接下来看它模块中三个实现类

二,Spring Container

主要指定了默认的配置文件路径(自动加载META-INF/spring目录下的所有Spring配置),通过ClassPathXmlApplicationContext来启动spring容器。

由于实现了Container接口,那么在resources下面找到com.alibaba.dubbo.container.Container文件中,可以看到spring=com.alibaba.dubbo.container.spring.SpringContainer,这是SPI扩展的相关知识。

三,Jetty Container

启动一个内嵌Jetty,用于汇报状态,但是在大量访问页面时,会影响服务器的线程和内存

配置:(配在java命令-D参数或者dubbo.properties中)

dubbo.jetty.port=8080 ----配置jetty启动端口

dubbo.jetty.directory=/foo/bar ----配置可通过jetty直接访问的目录,用于存放静态文件

dubbo.jetty.page=log,status,system ----配置显示的页面,缺省加载所有页面


四,Log4j Container

自动配置log4j的配置,在多进程启动时,自动给日志文件按进程分目录。

五,容器的启动

我们先来看Main类的main函数

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

final List<Container> containers = new ArrayList<Container>();
for (int i = 0; i < args.length; i ++) {
containers.add(loader.getExtension(args[i]));
}
logger.info("Use container type(" + Arrays.toString(args) + ") to run dubbo serivce.");

if ("true".equals(System.getProperty(SHUTDOWN_HOOK_KEY))) {
//优雅停止
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
for (Container container : containers) {
try {
container.stop();
logger.info("Dubbo " + container.getClass().getSimpleName() + " stopped!");
} catch (Throwable t) {
logger.error(t.getMessage(), t);
}
synchronized (Main.class) {
running = false;
Main.class.notify();
}
}
}
});
}
//根据参数启动容器
for (Container container : containers) {
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 e) {
e.printStackTrace();
logger.error(e.getMessage(), e);
System.exit(1);
}
synchronized (Main.class) {
while (running) {
try {
Main.class.wait();
} catch (Throwable e) {
}
}
}
}


所以我们在启动容器时候,可以选择spring、jetty、log4j、logback等参数。

六,容器的停机

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

此时有下面的情况

1,服务提供方

停止时,先标记为不接收新请求,新请求过来时直接报错,让客户端重试其它机器。

然后,检测线程池中的线程是否正在运行,如果有,等待所有线程执行完成,除非超时,则强制关闭。

2,服务消费方

停止时,不再发起新的调用请求,所有新的调用在客户端即报错。

然后,检测有没有请求的响应还没有返回,等待响应返回,除非超时,则强制关闭。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dubbo 源码