蚂蚁金服sofa rpc框架。公司想使用它作为架构的一部分,所以记录学习笔记。
1.从github下载源代码,版本为 5.6.0-SNAPSHOT,整个项目结构如下:
2.为了尽可能地只关注sofa 本身,所以没有下载 和springboot整合的项目,只是sofa本身。
3.本节学习sofa server端加载启动配置文件过程,即 获取 ServerConfig 过程。
4.在源码中example模块下quickstart中找到 QuickStartServer 这个类,debug启动;
5.
6.关键代码在 QuickStartServer类的第28行:
ServerConfig serverConfig = new ServerConfig();
/**
* 服务端配置
*
*/
public class ServerConfig extends AbstractIdConfig implements Serializable {
}
从上面红色箭头可以看到 大概调用流程是:
ServerConfig serverConfig = new ServerConfig() -> AbstractIdConfig()
AbstractIdConfig类中:
static {
RpcRuntimeContext.now();
}
进入到 RpcRuntimeContext 类中初始化
进而进入到 LoggerFactory 类的初始化
进而进入到 RpcConfigs 类的初始化
/**
* 配置加载器和操作入口
*/
public class RpcConfigs {
/**
* 全部配置
*/
private final static ConcurrentMap<String, Object> CFG = new ConcurrentHashMap<String, Object>();
/**
* 配置变化监听器
*/
private final static ConcurrentMap<String, List<RpcConfigListener>> CFG_LISTENER = new ConcurrentHashMap<String, List<RpcConfigListener>>();
static {
init(); // 加载配置文件
}
// ... ...
}
关键是上面 init()方法,加载配置文件;
private static void init() {
try {
// loadDefault
String json = FileUtils.file2String(RpcConfigs.class, "rpc-config-default.json", "UTF-8");
Map map = JSON.parseObject(json, Map.class);
CFG.putAll(map);
// loadCustom
loadCustom("sofa-rpc/rpc-config.json");
loadCustom("META-INF/sofa-rpc/rpc-config.json");
// load system properties
CFG.putAll(new HashMap(System.getProperties())); // 注意部分属性可能被覆盖为字符串
} catch (Exception e) {
throw new SofaRpcRuntimeException("Catch Exception when load RpcConfigs", e);
}
}
我们先看 loadDefault下面那一行代码:
String json = FileUtils.file2String(RpcConfigs.class, "rpc-config-default.json", "UTF-8");
FileUtils所在位置如下【common模块下com.alipay.sofa.rpc.common.utils.FileUtils】:
rpc-config-default.json 内容如下:
/*
本文件为SOFA RPC客户端内置的默认配置文件。
用户可以在自己的工程中自定义rpc-config.json进行默认配置覆盖。
所有的属性均可配置。(通过-D或者setProperty)
PS:大家也看到了,本JSON文档是支持注释的,而标准JSON是不支持的,这属于宽松的的json格式
*/
{
/*-------------RPC框架内部使用配置项-------------*/
// 本配置文件加载顺序,越大越后加载
"rpc.config.order": 0,
// 日志实现,日志早于配置加载,所以不能适应Extension机制
"logger.impl": "com.alipay.sofa.rpc.log.SLF4JLoggerImpl",
// 扩展点加载的路径
"extension.load.path": [
"META-INF/services/sofa-rpc/",
"META-INF/services/"
],
// 需要被加载的模块列表,多个用逗号隔开
"module.load.list" : "*",
/*-------------RPC框架内部使用配置项-------------*/
/*-------------系统运行时相关配置开始-------------*/
// 0代表自动判断,也可以自定义注入,或者启动参数注入
"system.cpu.cores": 0,
// 是否允许线程上下文携带自定义参数,默认true,关闭后,可能tracer等会失效,但是会提高性能
"context.attachment.enable": true,
// 是否启动事件总线,关闭后,可能tracer等会失效,但是可以提高性能
"event.bus.enable": true,
// 主动监听JVM关闭事件,默认true,如果有外部管理框架,可以由外部开启回收
"jvm.shutdown.hook": true,
// 是否增加序列化安全黑名单,关闭后可提供性能
"serialize.blacklist.enable": false,
// 是否支持多ClassLoader支持,如果是单ClassLoader环境,可以关闭提高性能
"multiple.classloader.enable": false,
// 是否允许请求和响应透传数据,关闭后,会提高性能
"invoke.baggage.enable": false,
/*-------------系统运行时相关配置开始-------------*/
/*-------------默认配置值开始-------------*/
// 默认Provider启动器
"default.provider.bootstrap": "sofa",
// 默认Consumer启动器
"default.consumer.bootstrap": "sofa",
// 默认uniqueId 做为服务唯一标识
"default.uniqueId": "",
// 默认version 不做为服务唯一标识
"default.version": "",
// 默认分组 不做为服务唯一标识
"default.group": "",
// 默认注册中心
"default.registry": "zookeeper",
// 默认协议
"default.protocol": "bolt",
// 默认序列化
"default.serialization": "hessian2",
// 默认压缩算法
"default.compress": "snappy",
// 默认代理类
"default.proxy": "javassist",
// 默认字符集
"default.charset": "UTF-8",
// 默认网络层
"default.transport": "netty4",
// 默认tracer实现
"default.tracer": "",
/*-------------默认配置值结束-------------*/
/*-------------Registry相关配置开始-------------*/
// 注册中心地址发现服务 的地址
"registry.index.address": "",
/* 默认连注册中心的超时时间*/
"registry.connect.timeout": 20000,
// 注册中心等待结果的超时时间
"registry.disconnect.timeout": 10000,
// 注册中心调用超时时间
"registry.invoke.timeout": 10000,
// 注册中心心跳发送间隔
"registry.heartbeat.period": 30000,
// 注册中心重建连接的间隔
"registry.reconnect.period": 30000,
// 是否开启有注册中心的批量注册/反注册 boolean 默认true,重连或者销毁时采用批量的方式。配为false则采取旧方式。 1.6.0
"registry.batch": false,
// 如果开启,批量的条数
"registry.batch.size": 10,
/*-------------Registry相关配置开始-------------*/
/*-------------Server相关配置开始-------------*/
// 默认绑定网卡
"server.host": "0.0.0.0",
// 端口段开始
"server.port.start": 12200,
// 端口段结束
"server.port.end": 65535,
// 默认contextPath
"server.context.path": "",
// 默认io线程大小,推荐自动设置
"server.ioThreads": 0,
// 默认业务线程池类型
"server.pool.type": "cached",
// 默认业务线程池最小
"server.pool.core": 20,
// 默认业务线程池最大
"server.pool.max": 200,
// 是否允许telnet,针对自定义协议
"server.telnet": true,
// 默认普通业务线程池队列
"server.pool.queue.type": "normal",
// 默认业务线程池队列大小
"server.pool.queue": 0,
// 默认业务线程池回收时间
"server.pool.aliveTime": 60000,
// 默认业务线程池是否初始化核心线程
"server.pool.pre.start": false,
// 最大支持长连接
"server.accepts": 100000,
// 是否启动epoll
"server.epoll": false,
// 是否hold住端口,true的话随主线程退出而退出,false的话则要主动退出
"server.daemon": false,
// 端口是否自适应,如果端口被占用,自动+1
"server.adaptive.port": false,
// 服务端是否自动启动
"server.auto.start": true,
// 服务端关闭超时时间
"server.stop.timeout": 20000,
/*-------------Server相关配置结束-------------*/
/*-------------Provider&Consumer公共配置开始-------------*/
//默认服务是否注册
"service.register": true,
//默认服务是否订阅
"service.subscribe": true,
/*-------------Provider&Consumer公共配置公共配置结束-------------*/
/*-------------Provider相关配置开始-------------*/
//默认服务端权重
"provider.weight": 100,
// 默认发布延迟,代表spring启动后触发
"provider.delay": -1,
// 默认发布方法:全部
"provider.include": "*",
// 默认不发布方法
"provider.exclude": "",
// 默认动态注册,false代表不主动发布
"provider.dynamic": true,
// 接口优先级
"provider.priority": 0,
//服务端调用超时, 不打断执行。0表示不判断
"provider.invoke.timeout": 0,
//接口下每方法的最大可并行执行请求数,配置-1关闭并发过滤器,等于0表示开启过滤但是不限制
"provider.concurrents": 0,
// 同一个服务(接口协议uniqueId相同)的最大发布次数,防止由于代码bug导致重复发布。注意:后面的发布可能会覆盖前面的实现
"provider.repeated.export.limit": 1,
/*-------------Provider相关配置结束-------------*/
/*-------------Consumer相关配置开始-------------*/
// 集群策略
"consumer.cluster": "failover",
// 默认连接全部建立长连接
"consumer.connectionHolder": "all",
// 默认单分组
"consumer.addressHolder": "singleGroup",
// 负载均衡
"consumer.loadBalancer": "random",
//默认失败重试次数
"consumer.retries": 0,
//接口下每方法的最大可并行执行请求数,配置-1关闭并发过滤器,等于0表示开启过滤但是不限制
"consumer.concurrents": 0,
// 默认是否异步
"consumer.invokeType": "sync",
// 默认不延迟加载
"consumer.lazy": false,
// 默认粘滞连接
"consumer.sticky": false,
// 是否jvm内部调用(provider和consumer配置在同一个jvm内,则走本地jvm内部,不走远程)
"consumer.inJVM": false,
// 是否强依赖(即没有服务节点就启动失败)
"consumer.check": false,
// 默认长连接数
"consumer.connection.num": 1,
// 默认consumer连provider超时时间
"consumer.connect.timeout": 5000,
// 默认consumer断开时等待结果的超时时间
"consumer.disconnect.timeout": 10000,
// 默认consumer调用provider超时时间
"consumer.invoke.timeout": 3000,
// 心跳发送间隔
"consumer.heartbeat.period": 30000,
// 重建连接间隔
"consumer.reconnect.period": 10000,
// 等待地址时间,-1表示一直等
"consumer.address.wait": -1,
// 同一个服务(接口协议uniqueId相同)的最大引用次数,防止由于代码bug导致重复引用,每次引用都会生成一个代理类对象
"consumer.repeated.reference.limit": 3,
// 本地缓存的StreamObserver最大实例数
"stream.observer.max.size": 10000,
// 本地缓存的Callback最大实例数
"callback.max.size": 1000,
// 弹性连接的连接数,按照服务者数量的百分比进行计算
"consumer.connect.elastic.precent": 0,
// 弹性连接的连接数
"consumer.connect.elastic.size": 5,
/*-------------Consumer相关配置结束-------------*/
/*-------------异步队列相关配置开始-------------*/
// 默认回调线程池最小
"async.pool.core": 10,
// 默认回调线程池最大
"async.pool.max": 200,
// 默认回调线程池队列
"async.pool.queue": 256,
// 默认回调线程池回收时间
"async.pool.time": 60000,
/*-------------异步队列相关配置结束-------------*/
/*-------------Transport层相关配置开始-------------*/
// 使用epoll
"transport.use.epoll": false,
//默认数据包大小 8*1024*1024
"transport.payload.max": 8388608,
// 客户端io线程数,默认 max(4,cpu+1)
"transport.client.io.threads": 0,
// 即I/O操作和用户自定义任务的执行时间比为1:1
"transport.client.io.ratio": 50,
"transport.server.backlog": 35536,
"transport.server.reuseAddr": true,
"transport.server.keepAlive": true,
"transport.server.tcpNoDelay": true,
"transport.server.io.ratio": 50,
// boss线程,默认max(4,cpu/2)
"transport.server.boss.threads": 0,
// 服务端IO线程 max(8,cpu+1)
"transport.server.io.threads": 0,
// 最大长连接
//"transport.server.max.connection" : 65536,
// 是否允许telnet
//"transport.server.telnet" : true,
// 是否守护线程,true随主线程退出而退出,false需要主动退出
//"transport.server.daemon" : true,
// 线程方法模型
"transport.server.dispatcher": "",
// 是否一个端口支持多协议
"transport.server.protocol.adaptive": true,
// buffer默认大小
"transport.buffer.size": 8192,
// 写入的buffer水位最大值
"transport.buffer.max": 32768,
// 写入的buffer水位最小值
"transport.buffer.min": 1024,
// 是否跨接口长链接复用
"transport.connection.reuse": true,
// 是否开启压缩
"compress.open": false,
// 开启压缩的大小基线
"compress.size.baseline": 2048,
//Whether the Http2 Cleartext protocol client uses Prior Knowledge to start Http2
"transport.client.h2c.usePriorKnowledge": true,
/*-------------Transport层相关配置结束-------------*/
/*
*其它 TODO
*/
// Consumer调用时是否发生信息 boolean 默认true,服务端拿到调用端的自动部署应用信息。配为false,服务端拿不到调用者信息 1.6.0
"invoke.send.app": false,
// 序列化时是否检查父子类(声明参数和传入值是父子类) boolean 默认true,如果业务不存在这种情况可以配置为false,提高性能 1.0.0
"serialize.check.class": false,
// 序列化是否检测循环引用类型 string 默认true,针对c++等调用者进行关闭 1.6.0
"serialize.check.reference": false,
// 客户端是否使用epoll(针对linux) boolean 默认false,Linux开启epoll可提高性能 1.0.3
"transport.consumer.epoll": false,
// 是否检测系统时间,需要filter配合
"check.system.time": false,
//计数器服务调用步长 int 默认1,每次丢调用计数器,调大可以提高性能但会减低精准 1.2.0
"counter.batch": false,
//json序列化是否返回null字段。 boolean 默认false,默认只返回有属性的字段。打开会降低效率。 1.5.1
"json.serialize.fill.empty": false,
// consumer的服务端列表是否可被清空 boolean 默认false,默认不能被清空(最后的清空请求被忽略),防止删全部节点等误操作,但是会影响列表的准确性。 1.6.0
"consumer.provider.nullable": false,
// json序列化的时候,开启的特性 string 默认空,参见fastjson.serializer.SerializerFeature,多个逗号分隔 1.6.0
"json.serializer.features": false,
// json解析的时候,开启的特性 string 默认空,参见fastjson.parser.Feature,多个逗号分隔 1.6.0
"json.parser.features": false,
// 心跳在IO线程吗? TODO
"transport.heart.io": true,
// 协商请求在IO线程执行吗? TODO
"transport.negotiator.async": false,
//是否所有客户端共享一个重连线程
"consumer.share.reconnect.thread": false,
//是否禁止开启lookout采集信息
"lookout.collect.disable": false
}
把json数据转换成map,保存到全局配置中
/**
* 全部配置
*/
private final static ConcurrentMap<String, Object> CFG = new ConcurrentHashMap<String, Object>();
// .....
Map map = JSON.parseObject(json, Map.class);
CFG.putAll(map);
下面说 loadCustom("sofa-rpc/rpc-config.json");
/**
* 加载自定义配置文件
*
* @param fileName 文件名
* @throws IOException 加载异常
*/
private static void loadCustom(String fileName) throws IOException {
ClassLoader classLoader = ClassLoaderUtils.getClassLoader(RpcConfigs.class);
Enumeration<URL> urls = classLoader != null ? classLoader.getResources(fileName)
: ClassLoader.getSystemResources(fileName);
if (urls != null) { // 可能存在多个文件
List<CfgFile> allFile = new ArrayList<CfgFile>();
while (urls.hasMoreElements()) {
// 读取每一个文件
URL url = urls.nextElement();
InputStreamReader input = null;
BufferedReader reader = null;
try {
input = new InputStreamReader(url.openStream(), "utf-8");
reader = new BufferedReader(input);
StringBuilder context = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
context.append(line).append("\n");
}
Map map = JSON.parseObject(context.toString(), Map.class);
Integer order = (Integer) map.get(RpcOptions.RPC_CFG_ORDER);
allFile.add(new CfgFile(url, order == null ? 0 : order, map));
} finally {
if (reader != null) {
reader.close();
}
if (input != null) {
input.close();
}
}
}
Collections.sort(allFile, new OrderedComparator<CfgFile>()); // 从小到大排下序
for (CfgFile file : allFile) {
CFG.putAll(file.getMap()); // 顺序加载,越大越后加载
}
}
}
加载的 sofa-rpc/rpc-config.json 存在于如下位置 :
下面说 loadCustom("META-INF/sofa-rpc/rpc-config.json");
默认没有文件加载到全局配置文件中。
RpcConfigs 类初始化线束!!!!!
回到 RpcRuntimeContext 类的初始化:
static {
put(RpcConstants.CONFIG_KEY_RPC_VERSION, Version.RPC_VERSION);
// 初始化一些上下文
initContext();
// 初始化其它模块
ModuleFactory.installModules();
// 增加jvm关闭事件
if (RpcConfigs.getOrDefaultValue(RpcOptions.JVM_SHUTDOWN_HOOK, true)) {
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
if (LOGGER.isWarnEnabled()) {
LOGGER.warn("SOFA RPC Framework catch JVM shutdown event, Run shutdown hook now.");
}
destroy(false);
}
}, "SOFA-RPC-ShutdownHook"));
}
}
先说 初始化一些上下文:简单的几个上下文属性从RpcConfig配置中读取设置;
初始化其它模块 开始:
/**
* 加载全部模块
*/
public static void installModules() {
//【关键代码】
ExtensionLoader<Module> loader = ExtensionLoaderFactory.getExtensionLoader(Module.class);
String moduleLoadList = RpcConfigs.getStringValue(RpcOptions.MODULE_LOAD_LIST);
for (Map.Entry<String, ExtensionClass<Module>> o : loader.getAllExtensions().entrySet()) {
String moduleName = o.getKey();
// 【关键行代码,会调用上面模块加载器中加载的Module实例】
Module module = o.getValue().getExtInstance();
// judge need load from rpc option
if (needLoad(moduleLoadList, moduleName)) {
// judge need load from implement
if (module.needLoad()) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Install Module: {}", moduleName);
}
module.install();
INSTALLED_MODULES.put(moduleName, module);
} else {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("The module " + moduleName + " does not need to be loaded.");
}
}
} else {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("The module " + moduleName + " is not in the module load list.");
}
}
}
}
ExtensionLoader<Module> loader = ExtensionLoaderFactory.getExtensionLoader(Module.class); 开始
/**
* Get extension loader by extensible class with listener
*
* @param clazz Extensible class
* @param listener Listener of ExtensionLoader
* @param <T> Class
* @return ExtensionLoader of this class
*/
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> clazz, ExtensionLoaderListener<T> listener) {
ExtensionLoader<T> loader = LOADER_MAP.get(clazz);
if (loader == null) {
synchronized (ExtensionLoaderFactory.class) {
loader = LOADER_MAP.get(clazz);
if (loader == null) {
// 关键代码行!!!!
loader = new ExtensionLoader<T>(clazz, listener);
LOADER_MAP.put(clazz, loader);
}
}
}
return loader;
}
关键看上面代码中的 ExtensionLoaderFactory类中:
loader = new ExtensionLoader<T>(clazz, listener);
ExtensionLoader类:
/**
* @param path path必须以/结尾
*/
protected synchronized void loadFromFile(String path) {
// 默认如果不指定文件名字,就是接口名
String file = StringUtils.isBlank(extensible.file()) ? interfaceName : extensible.file().trim();
String fullFileName = path + file;
try {
ClassLoader classLoader = ClassLoaderUtils.getClassLoader(getClass());
// 关键代码行!!!!
loadFromClassLoader(classLoader, fullFileName);
} catch (Throwable t) {
if (LOGGER.isErrorEnabled()) {
LOGGER.error("Failed to load extension of extensible " + interfaceName + " from path:" + fullFileName,
t);
}
}
}
下面进入关键代码行:
loadFromClassLoader(classLoader, fullFileName);
protected void loadFromClassLoader(ClassLoader classLoader, String fullFileName) throws Throwable {
Enumeration<URL> urls = classLoader != null ? classLoader.getResources(fullFileName)
: ClassLoader.getSystemResources(fullFileName);
// 可能存在多个文件。
if (urls != null) {
while (urls.hasMoreElements()) {
// 读取一个文件
URL url = urls.nextElement();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Loading extension of extensible {} from classloader: {} and file: {}",
interfaceName, classLoader, url);
}
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
String line;
while ((line = reader.readLine()) != null) {
// 关键代码行!!!!
readLine(url, line);
}
} catch (Throwable t) {
if (LOGGER.isWarnEnabled()) {
LOGGER.warn("Failed to load extension of extensible " + interfaceName
+ " from classloader: " + classLoader + " and file:" + url, t);
}
} finally {
if (reader != null) {
reader.close();
}
}
}
}
}
上面第一个路径 META-INF/services/sofa-rpc/ 配置模块module加载完成,下面同样进入第2个路径 META-INF/services/ 中加载模块,
默认是没有module加载的!
protected void readLine(URL url, String line) {
String[] aliasAndClassName = parseAliasAndClassName(line);
if (aliasAndClassName == null || aliasAndClassName.length != 2) {
return;
}
String alias = aliasAndClassName[0];
String className = aliasAndClassName[1];
// 读取配置的实现类
Class tmp;
try {
tmp = ClassUtils.forName(className, false);
} catch (Throwable e) {
// ...
return;
}
if (!interfaceClass.isAssignableFrom(tmp)) {
throw new IllegalArgumentException("Error when load extension of extensible " + interfaceName +
" from file:" + url + ", " + className + " is not subtype of interface.");
}
Class<? extends T> implClass = (Class<? extends T>) tmp;
// 检查是否有可扩展标识
Extension extension = implClass.getAnnotation(Extension.class);
if (extension == null) {
throw new IllegalArgumentException("Error when load extension of extensible " + interfaceName +
" from file:" + url + ", " + className + " must add annotation @Extension.");
} else {
String aliasInCode = extension.value();
if (StringUtils.isBlank(aliasInCode)) {
// 扩展实现类未配置@Extension 标签
throw new IllegalArgumentException("Error when load extension of extensible " + interfaceClass +
" from file:" + url + ", " + className + "'s alias of @Extension is blank");
}
if (alias == null) {
// spi文件里没配置,用代码里的
alias = aliasInCode;
} else {
// spi文件里配置的和代码里的不一致
if (!aliasInCode.equals(alias)) {
throw new IllegalArgumentException("Error when load extension of extensible " + interfaceName +
" from file:" + url + ", aliases of " + className + " are " +
"not equal between " + aliasInCode + "(code) and " + alias + "(file).");
}
}
// 接口需要编号,实现类没设置
if (extensible.coded() && extension.code() < 0) {
throw new IllegalArgumentException("Error when load extension of extensible " + interfaceName +
" from file:" + url + ", code of @Extension must >=0 at " + className + ".");
}
}
// 不可以是default和*
if (StringUtils.DEFAULT.equals(alias) || StringUtils.ALL.equals(alias)) {
throw new IllegalArgumentException("Error when load extension of extensible " + interfaceName +
" from file:" + url + ", alias of @Extension must not \"default\" and \"*\" at " + className + ".");
}
// 检查是否有存在同名的
ExtensionClass old = all.get(alias);
ExtensionClass<T> extensionClass = null;
if (old != null) {
// 如果当前扩展可以覆盖其它同名扩展
if (extension.override()) {
// 如果优先级还没有旧的高,则忽略
if (extension.order() < old.getOrder()) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Extension of extensible {} with alias {} override from {} to {} failure, " +
"cause by: order of old extension is higher",
interfaceName, alias, old.getClazz(), implClass);
}
} else {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Extension of extensible {} with alias {}: {} has been override to {}",
interfaceName, alias, old.getClazz(), implClass);
}
// 如果当前扩展可以覆盖其它同名扩展
//【关键代码行】
extensionClass = buildClass(extension, implClass, alias);
}
}
// 如果旧扩展是可覆盖的
else {
if (old.isOverride() && old.getOrder() >= extension.order()) {
// 如果已加载覆盖扩展,再加载到原始扩展
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Extension of extensible {} with alias {}: {} has been loaded, ignore origin {}",
interfaceName, alias, old.getClazz(), implClass);
}
} else {
// 如果不能被覆盖,抛出已存在异常
throw new IllegalStateException(
"Error when load extension of extensible " + interfaceClass + " from file:" + url +
", Duplicate class with same alias: " + alias + ", " + old.getClazz() + " and " + implClass);
}
}
} else {
//【关键代码行】
extensionClass = buildClass(extension, implClass, alias);
}
if (extensionClass != null) {
// 检查是否有互斥的扩展点
for (Map.Entry<String, ExtensionClass<T>> entry : all.entrySet()) {
ExtensionClass existed = entry.getValue();
if (extensionClass.getOrder() >= existed.getOrder()) {
// 新的优先级 >= 老的优先级,检查新的扩展是否排除老的扩展
String[] rejection = extensionClass.getRejection();
if (CommonUtils.isNotEmpty(rejection)) {
for (String rej : rejection) {
existed = all.get(rej);
if (existed == null || extensionClass.getOrder() < existed.getOrder()) {
continue;
}
ExtensionClass removed = all.remove(rej);
if (removed != null) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info(
"Extension of extensible {} with alias {}: {} has been reject by new {}",
interfaceName, removed.getAlias(), removed.getClazz(), implClass);
}
}
}
}
} else {
String[] rejection = existed.getRejection();
if (CommonUtils.isNotEmpty(rejection)) {
for (String rej : rejection) {
if (rej.equals(extensionClass.getAlias())) {
// 被其它扩展排掉
if (LOGGER.isInfoEnabled()) {
LOGGER.info(
"Extension of extensible {} with alias {}: {} has been reject by old {}",
interfaceName, alias, implClass, existed.getClazz());
return;
}
}
}
}
}
}
//【加载成功】
loadSuccess(alias, extensionClass);
}
}
private ExtensionClass<T> buildClass(Extension extension, Class<? extends T> implClass, String alias) {
ExtensionClass<T> extensionClass = new ExtensionClass<T>(implClass, alias);
extensionClass.setCode(extension.code());
extensionClass.setSingleton(extensible.singleton());
extensionClass.setOrder(extension.order());
extensionClass.setOverride(extension.override());
extensionClass.setRejection(extension.rejection());
return extensionClass;
}
private void loadSuccess(String alias, ExtensionClass<T> extensionClass) {
if (listener != null) {
try {
listener.onLoad(extensionClass); // 加载完毕,通知监听器
all.put(alias, extensionClass);
} catch (Exception e) {
LOGGER.error("Error when load extension of extensible " + interfaceClass + " with alias: "
+ alias + ".", e);
}
} else {
all.put(alias, extensionClass);
}
}
ExtensionLoader<Module> loader = ExtensionLoaderFactory.getExtensionLoader(Module.class); 结束!!!
下面回到 加载全部模块方法:
/**
* 加载全部模块
*/
public static void installModules() {
//【上面已经花了大段代码说明】
ExtensionLoader<Module> loader = ExtensionLoaderFactory.getExtensionLoader(Module.class);
String moduleLoadList = RpcConfigs.getStringValue(RpcOptions.MODULE_LOAD_LIST);
for (Map.Entry<String, ExtensionClass<Module>> o : loader.getAllExtensions().entrySet()) {
String moduleName = o.getKey();
//【会调用上面模块加载器已经加载的Module实例】
Module module = o.getValue().getExtInstance();
// judge need load from rpc option
if (needLoad(moduleLoadList, moduleName)) {
// judge need load from implement
if (module.needLoad()) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Install Module: {}", moduleName);
}
//【关键代码】
module.install();
INSTALLED_MODULES.put(moduleName, module);
} else {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("The module " + moduleName + " does not need to be loaded.");
}
}
} else {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("The module " + moduleName + " is not in the module load list.");
}
}
}
}
上面 FaultToleranceModule 类是 上面一个具体的Module配置,
上面是 FaultToleranceModule 类中 定义的 Regulator 实例初始化。上面 module.install()方法:
然后就是各个模块的 install()方法运行!!!
初始化其它模块 结束!!!
最后回到
下面进入 destroy(false) 方法中:
/**
* 销毁方法
*
* @param active 是否主动销毁
*/
private static void destroy(boolean active) {
// TODO 检查是否有其它需要释放的资源
RpcRunningState.setShuttingDown(true);
for (Destroyable.DestroyHook destroyHook : DESTROY_HOOKS) {
destroyHook.preDestroy();
}
List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>();
for (ProviderBootstrap bootstrap : EXPORTED_PROVIDER_CONFIGS) {
providerConfigs.add(bootstrap.getProviderConfig());
}
// 先反注册服务端
List<Registry> registries = RegistryFactory.getRegistries();
if (CommonUtils.isNotEmpty(registries) && CommonUtils.isNotEmpty(providerConfigs)) {
for (Registry registry : registries) {
registry.batchUnRegister(providerConfigs);
}
}
// 关闭启动的端口
ServerFactory.destroyAll();
// 关闭发布的服务
for (ProviderBootstrap bootstrap : EXPORTED_PROVIDER_CONFIGS) {
bootstrap.unExport();
}
// 关闭调用的服务
for (ConsumerBootstrap bootstrap : REFERRED_CONSUMER_CONFIGS) {
ConsumerConfig config = bootstrap.getConsumerConfig();
if (!CommonUtils.isFalse(config.getParameter(RpcConstants.HIDDEN_KEY_DESTROY))) { // 除非不让主动unrefer
bootstrap.unRefer();
}
}
// 关闭注册中心
RegistryFactory.destroyAll();
// 关闭客户端的一些公共资源
ClientTransportFactory.closeAll();
// 卸载模块
if (!RpcRunningState.isUnitTestMode()) {
ModuleFactory.uninstallModules();
}
// 卸载钩子
for (Destroyable.DestroyHook destroyHook : DESTROY_HOOKS) {
destroyHook.postDestroy();
}
// 清理缓存
RpcCacheManager.clearAll();
RpcRunningState.setShuttingDown(false);
}