dubbo-源码阅读之容器启动
dubbo Main
例子
public class Start {
public static void main(String[] args) throws Exception {
com.alibaba.dubbo.container.Main.main(args);
}
}
源码
public class Main {
//系统变量
public static final String CONTAINER_KEY = "dubbo.container";
public static final String SHUTDOWN_HOOK_KEY = "dubbo.shutdown.hook";
private static final Logger logger = LoggerFactory.getLogger(Main.class);
//SPI的container Loader容器
private static final ExtensionLoader<Container> loader = ExtensionLoader.getExtensionLoader(Container.class);
private static final ReentrantLock LOCK = new ReentrantLock();
private static final Condition STOP;
public Main() {
}
public static void main(String[] args) {
try {
//如果没有启动参数
if (args == null || args.length == 0) {
//获得系统变量 如jvm参数配置的-Ddubbo.container=spiKey 如果没有则使用loader.getDefaultExtensionName()的
String config = ConfigUtils.getProperty("dubbo.container", loader.getDefaultExtensionName());
//分割
args = Constants.COMMA_SPLIT_PATTERN.split(config);
}
//容器 可以多容器启动
final List<Container> containers = new ArrayList();
for(int i = 0; i < args.length; ++i) {
//spi获取对应容器实现
containers.add(loader.getExtension(args[i]));
}
logger.info("Use container type(" + Arrays.toString(args) + ") to run dubbo serivce.");
/**
* 埋点 jvm关闭时 关闭容器
*kill pid会优雅关闭 则有新的请求拒绝 等没有进行中的请求 才关闭
*kill -9并不会优雅关闭
*/
if ("true".equals(System.getProperty("dubbo.shutdown.hook"))) {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
Iterator i$ = containers.iterator();
//遍历容器执行stop
while(i$.hasNext()) {
Container container = (Container)i$.next();
try {
container.stop();
Main.logger.info("Dubbo " + container.getClass().getSimpleName() + " stopped!");
} catch (Throwable var8) {
Main.logger.error(var8.getMessage(), var8);
}
try {
Main.LOCK.lock();
//类型Object的notify
Main.STOP.signal();
} finally {
Main.LOCK.unlock();
}
}
}
});
}
Iterator i$ = containers.iterator();
//循环启动容器
while(i$.hasNext()) {
Container container = (Container)i$.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 var10) {
var10.printStackTrace();
logger.error(var10.getMessage(), var10);
System.exit(1);
}
try {
LOCK.lock();
/**
* 阻塞 防止应用程序结束
* 类似object的wait()
*/
STOP.await();
} catch (InterruptedException var8) {
logger.warn("Dubbo service server stopped, interrupted by other thread!", var8);
} finally {
LOCK.unlock();
}
}
static {
//condition可参考资料https://blog.csdn.net/andyzhaojianhui/article/details/79361454
STOP = LOCK.newCondition();
}
}
loader.getDefaultExtensionName()
public class ExtensionLoader<T> {
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder();
public String getDefaultExtensionName() {
this.getExtensionClasses();
return this.cachedDefaultName;
}
private Map<String, Class<?>> getExtensionClasses() {
//默认Holder容器是空的
Map<String, Class<?>> classes = (Map)this.cachedClasses.get();
if (classes == null) {
Holder var2 = this.cachedClasses;
synchronized(this.cachedClasses) {
//防止缓存穿透 重复加载 加了一层判断
classes = (Map)this.cachedClasses.get();
if (classes == null) {
//真正加载的地方
classes = this.loadExtensionClasses();
this.cachedClasses.set(classes);
}
}
}
return classes;
}
private Map<String, Class<?>> loadExtensionClasses() {
/**
* 获得Container上的SPI注解 private static final ExtensionLoader<Container> loader = ExtensionLoader.getExtensionLoader(Container.class);
* type为Container
*/
SPI defaultAnnotation = (SPI)this.type.getAnnotation(SPI.class);
if (defaultAnnotation != null) {
//获取SPI上面的名字
String value = defaultAnnotation.value();
if ((value = value.trim()).length() > 0) {
String[] names = NAME_SEPARATOR.split(value);
if (names.length > 1) {
throw new IllegalStateException("more than 1 default extension name on extension " + this.type.getName() + ": " + Arrays.toString(names));
}
if (names.length == 1) {
this.cachedDefaultName = names[0];
}
}
}
Map<String, Class<?>> extensionClasses = new HashMap();
//加载这个目录下的spi文件配置 META-INF/dubbo/internal/com.alibaba.dubbo.container.Container
this.loadDirectory(extensionClasses, "META-INF/dubbo/internal/");
//加载这个目录下的spi文件配置 META-INF/dubbo/com.alibaba.dubbo.container.Container
this.loadDirectory(extensionClasses, "META-INF/dubbo/");
//加载这个目录下的spi文件配置META-INF/dubbo/services/com.alibaba.dubbo.container.Container
this.loadDirectory(extensionClasses, "META-INF/services/");
return extensionClasses;
}
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir) {
//加载这个目录下的spi文件配置 META-INF/dubbo/internal/com.alibaba.dubbo.container.Container
String fileName = dir + this.type.getName();
try {
ClassLoader classLoader = findClassLoader();
Enumeration urls;
if (classLoader != null) {
urls = classLoader.getResources(fileName);
} else {
urls = ClassLoader.getSystemResources(fileName);
}
if (urls != null) {
while(urls.hasMoreElements()) {
java.net.URL resourceURL = (java.net.URL)urls.nextElement();
this.loadResource(extensionClasses, classLoader, resourceURL);
}
}
} catch (Throwable var7) {
logger.error("Exception when load extension class(interface: " + this.type + ", description file: " + fileName + ").", var7);
}
}
}
SpringContainer
例子

源码
public class SpringContainer implements Container {
//可以系统变量指定spring xml配置
public static final String SPRING_CONFIG = "dubbo.spring.config";
//默认的位置
public static final String DEFAULT_SPRING_CONFIG = "classpath*:META-INF/spring/*.xml";
private static final Logger logger = LoggerFactory.getLogger(com.alibaba.dubbo.container.spring.SpringContainer.class);
static ClassPathXmlApplicationContext context;
public SpringContainer() {
}
public static ClassPathXmlApplicationContext getContext() {
return context;
}
public void start() {
//获取系统变量指定的spring配置文件位置
String configPath = ConfigUtils.getProperty("dubbo.spring.config");
if (configPath == null || configPath.length() == 0) {
//没有指定取默认的
configPath = "classpath*:META-INF/spring/*.xml";
}
//初始化spring容器
context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+"));
//start开始解析spring相关xml 以及dubbo基于spring2.0 schema解析dubbo相关配置以及初始化
context.start();
}
public void stop() {
try {
if (context != null) {
context.stop();
context.close();
context = null;
}
} catch (Throwable var2) {
logger.error(var2.getMessage(), var2);
}
}
}
dubbo-源码阅读之容器启动的更多相关文章
- 【Dubbo源码阅读系列】之远程服务调用(上)
今天打算来讲一讲 Dubbo 服务远程调用.笔者在开始看 Dubbo 远程服务相关源码的时候,看的有点迷糊.后来慢慢明白 Dubbo 远程服务的调用的本质就是动态代理模式的一种实现.本地消费者无须知道 ...
- 【Dubbo源码阅读系列】服务暴露之远程暴露
引言 什么叫 远程暴露 ?试着想象着这么一种场景:假设我们新增了一台服务器 A,专门用于发送短信提示给指定用户.那么问题来了,我们的 Message 服务上线之后,应该如何告知调用方服务器,服务器 A ...
- 【Dubbo源码阅读系列】服务暴露之本地暴露
在上一篇文章中我们介绍 Dubbo 自定义标签解析相关内容,其中我们自定义的 XML 标签 <dubbo:service /> 会被解析为 ServiceBean 对象(传送门:Dubbo ...
- 【Dubbo源码阅读系列】之 Dubbo SPI 机制
最近抽空开始了 Dubbo 源码的阅读之旅,希望可以通过写文章的方式记录和分享自己对 Dubbo 的理解.如果在本文出现一些纰漏或者错误之处,也希望大家不吝指出. Dubbo SPI 介绍 Java ...
- Dubbo源码阅读顺序
转载: https://blog.csdn.net/heroqiang/article/details/85340958 Dubbo源码解析之配置解析篇,主要内容是<dubbo:service/ ...
- Fabric1.4源码解析: 链码容器启动过程
想写点东西记录一下最近看的一些Fabric源码,本文使用的是fabric1.4的版本,所以对于其他版本的fabric,内容可能会有所不同. 本文想针对Fabric中链码容器的启动过程进行源码的解析.这 ...
- spring源码:web容器启动(li)
web项目中可以集成spring的ApplicationContext进行bean的管理,这样使用起来bean更加便捷,能够利用到很多spring的特性.我们比较常用的web容器有jetty,tomc ...
- spring源码:web容器启动
web项目中可以集成spring的ApplicationContext进行bean的管理,这样使用起来bean更加便捷,能够利用到很多spring的特性.我们比较常用的web容器有jetty,tomc ...
- Dubbo源码阅读-服务导出
Dubbo服务导出过程始于Spring容器发布刷新事件,Dubbo在接收到事件后,会立即执行服务导出逻辑.整个逻辑大致可分为三个部分,第一部分是前置工作,主要用于检查参数,组装URL.第二部分是导出服 ...
随机推荐
- 从vue的组件传值着手浅谈观察者模式
首先,提到观察者模式,这不禁让我想到了MVVM,MVVM架构模式感觉用到了观察者的思想. 我们还是按照惯例,了解一下什么是观察者模式 观察者模式,类似发布订阅模式,完成这个动作首先最少得有两个不同的对 ...
- tomcat-性能优化参考
转摘 http://blog.csdn.net/lifetragedy/article/details/7708724. ###jdk1.6.未验证.仅供参考### linux环境下Tomcat调优 ...
- spring 获取url参数
1. usl格式: http://localhost:8080/contact/delete/3 java代码 @RequestMapping(value="/delete/{id}&quo ...
- sublime-1
1.提示找不到margo go get github.com/DisposaBoy/MarGo(该工具已经被作者清空了,大部分人在这一步就被卡住了) 如果你也是在第二步卡住了,那么可以按照我的方法进行 ...
- Linux文件归档工具——tar
Linux打包压缩命令——tar 一tar工具的介绍 Tar(Tape ARchive,磁带归档的缩写) NAME tar - manual page for tar 1.26 SYNOPSIS ta ...
- djangorestframework-jwt产生对方token
第一步是 通过jwt组件获得当前用户的token 第二步是 进行加密规则 需要用到base64模块进行加密 第三步 进行解密 按照规定的header payload signature 这种方式解密 ...
- CPU的历史
https://zhuanlan.zhihu.com/p/64537796 很多人都对电脑硬件有一点的了解,本人也算略懂一二,所以今天来为大家说说电脑的主要硬件之一––CPU(中央处理器). 那么我们 ...
- LA 3971 Assemble(二分)
题目: 给你b元钱,让你组装一台电脑,有n个配件,属性有 种类 名字 价格 品质,每种类型选至少一个,并且最小品质最大.输出这个最大的最小品质. 白书上说了,最小值最大的问题一般是二分来求解答案.在这 ...
- SCP-bzoj-1079
项目编号:bzoj-1079 项目等级:Safe 项目描述: 戳这里 特殊收容措施: DP.普通的状压状态数515,显然TLE+MLE,我们考虑把底数和幂换一换,压成155的状态数. 故状态设计为:f ...
- JMeter ServerAgent服务器资源监控插件
本文介绍对Linux服务器的服务进行压测时,使用jmeter serverAgent插件监控服务器资源. 1.插件准备 所需插件: JMeterPlugins-Extras.jar JMeterPlu ...