dubbo(三)服务运行容器Container
一、服务运行容器-Container
Dubbo中的其中一个角色,服务运行容器Container。他是一个独立的容器,如果项目比较轻,没用到Web特性,因此不想用Tomcat等Web容器,则可以使用Main方法加载Spring容器。
· Container容器启动原理
public class Main {
public static void main(String[] args) { //如果未配置容器实现,则默认使用Spring容器 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++) { //对配置的容器进行遍历与加载,通过SPI加载SpringContainer containers.add(loader.getExtension(args[i]));
} //... for (Container container : containers) { //启动SpringContainer容器 container.start();
logger.info("Dubbo " + container.getClass().getSimpleName() + " started!");
}
//...
}
}
Container实现类有很多种,但是这里默认通过SPI加载的是SpringContainer容器,最后通过SpringContainer.start()读取配置加载bean,启动容器。
public void start() { //配置文件路径 写死的 = classpath*:META-INF/spring/*.xml String configPath = ConfigUtils.getProperty(SPRING_CONFIG);
if (configPath == null || configPath.length() == 0) {
configPath = DEFAULT_SPRING_CONFIG;
}
context = new ClassPathXmlApplicationContext(configPath.split("[,\s]+"), false);
context.addApplicationListener(new DubboApplicationListener()); //注册优雅停机配置dubbo-container-shutdown-hook context.registerShutdownHook();
//通过context加载bean
context.refresh();
context.start();
}
· Container容器停止原理
通过kill PID关闭容器时,如果注册了dubbo-container-shutdown-hook则会进入以下代码优雅停机。
public static void main(String[] args) {
//...
if ("true".equals(System.getProperty(SHUTDOWN_HOOK_KEY))) {
Runtime.getRuntime().addShutdownHook(new Thread("dubbo-container-shutdown-hook") {
@Override
public void run() {
for (Container container : containers) {
try { //调用SpringContainer.stop停止容器 container.stop();
} catch (Throwable t) {
logger.error(t.getMessage(), t);
}
try {
LOCK.lock();
STOP.signal();
} finally {
LOCK.unlock();
}
}
}
});
}
//...
}
通过SpringContainer.stop()销毁bean和关闭容器。
原理:
(1)服务提供方
停止时,先标记为不接受新请求,新请求过来时直接报错,让客户端重试其他机器。然后检测线程池中的线程是否正在运行,如果有,等待所有线程执行完成,如果超时则强制关闭。
(2)服务消费方
停止时,不再发起新的请求,所有新的调用在客户端即报错。然后检测是否还有请求的响应没返回,等待返回,如果超时则强制关闭。
二、如何解析dubbo的bean
<dubbo:service interface="com.ywl.test.TestApi"
ref="testApi" retries="0" cluster="failfast" timeout="3000"/>
如上图所示,service、interface这些schema都是dubbo扩展的自定义解析配置,因此需要引入指定的dubbo自定义的schema。
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd
并且每个schema都有自己的解析类,dubbo标签对应的解析类,可以查看DubboNamespaceHandler类。
public void init() {
registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());}
如上图所示,dubbo:service对应的为DubboBeanDefinitionParser解析器。
· DubboBeanDefinitionParser
DubboBeanDefinitionParser会解析ref、service、timeout、version等元素,解析成spring的beanDefinition对象,注册到spring中。核心代码如下:
private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(beanClass);
beanDefinition.setLazyInit(false);
String id = element.getAttribute("id");
//...
if (id != null && id.length() > 0) {
if (parserContext.getRegistry().containsBeanDefinition(id)) {
throw new IllegalStateException("Duplicate spring bean id " + id);
} //注册到spring中
parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
beanDefinition.getPropertyValues().addPropertyValue("id", id);
} //...}
这里的注册其实就相当于往spring中的beanDefinitionMap中放入元素,key-dubbo配置的id,消费者为id,服务提供者为interface路径,value-配置的类解析成的beanDefinition对象。
三、总结
dubbo的使用其实也离不开spring容器的支持,dubbo与spring整合的核心在于DubboBeanDefinitionParser解析类。
下一篇会写下dubbo的服务发布原理。
- CentOS 6.3下 安装 Mono 3.2 和Jexus 5.4
- Python 项目实践三(Web应用程序)第四篇
- 负载均衡环境下缓存处理
- WordPress Ajax 异步加载 自定义评论表情
- “分期网”域名fenqi.wang以16888元成交
- Python 项目实践三(Web应用程序) 第三篇
- Python 项目实践三(Web应用程序)第二篇
- 第一个IronPython程序(之一)
- mono-3.4.0 源码安装时出现的问题 [do-install] Error 2 [install-pcl-targets] Error 1 解决方法
- 安装 IronPython
- Python 项目实践三(Web应用程序)第一篇
- Centos 7.0 安装Mono 3.4 和 Jexus 5.6
- 第一个IronPython程序(之二)
- Python 项目实践二(下载数据)第四篇
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 10行python代码制作笑死人不偿命的倒放gif
- “Hello Node.js” 这一次是你没见过的写法
- 作为DBA,你不得不掌握的压测工具
- Mac之vim普通命令使用
- selenium库的基本使用
- 高效大数据开发之 bitmap 思想的应用
- 从0到1实现一个虚拟DOM
- Xenomai XDDP example and Posix Compling
- 项目实践|基于Flink的用户行为日志分析系统
- 手把手教你用Matplotlib画一个小清新配色的商业图表
- 高并发场景下锁的使用技巧
- Struts2第四天:Struts2的拦截器和标签库
- kubernete编排技术八:使用operator管理有状态应用
- Spring第一天:Spring的概述、SpringIOC入门(XML)、Spring的Bean管理、Spring属性注入
- Flink的处理背压原理及问题-面试必备