配置加载
字数: 0 字 时长: 0 分钟
需求分析
RPC 框架在运行过程中会涉及到很多的配置信息,比如注册中心的地址、序列化方式、网络服务器端口等,因此我们需要一套全局配置加载功能,能够让 RPC 框架轻松从配置文件中读取配置。
在实现之前,我们先来了解一下业界标杆 Spring 是如何实现实现配置资源的加载和维护的。
Spring 使用 Environment
抽象接口来统一管理全局配置,它作为一个逻辑上的全局环境变量环境,整合了所有配置源(application
配置文件、系统变量、JNDI等),为整个应用提供一致的配置访问入口。
上面我列出了 Spring 环境变量模块的部分类图,实际上整个模块很复杂,涉及到了大量的设计模式,这里我们实现的简易 RPC 框架参照 Spring 配置模块简单实现即可。
1. 全局配置类
Spring 的 Environment
接口下有各种环境的具体实现,这里我们就简单创建一个标准环境的配置类 RpcConfig
即可。
2. 配置加载器
Spring 定义了 PropertyResolver
接口,下面有不同配置源的加载实现,这里我们创建一个 ConfigUtils
工具类作为我们的配置加载器。
3. 配置访问入口
Spring 使用 Environment
抽象接口作为配置访问入口,我们创建一个 RpcApplication
类作为统一的配置访问入口即可。
代码实现
RpcConfig
全局配置对象类
/**
* RPC 框架配置
*/
@Data
public class RpcConfig {
/**
* 名称
*/
private String name = "t-rpc";
/**
* 版本号
*/
private String version = "1.0";
/**
* 服务器主机名
*/
private String serverHost = "localhost";
/**
* 服务器端口号
*/
private Integer serverPort = 8080;
/**
* 是否需要启动 server
*/
private boolean needServer = false;
/**
* 模拟调用
*/
private boolean mock = false;
/**
* 序列化器
*/
private String serializer = SerializerKeys.JDK;
/**
* 注册中心配置
*/
private RegistryConfig registryConfig = new RegistryConfig();
/**
* 负载均衡器
*/
private String loadBalancer = LoadBalancerKeys.ROUND_ROBIN;
}
ConfigUtils
配置加载工具类
/**
* 配置工具类
*/
public class ConfigUtils {
public static <T> T loadConfig(Class<T> tClass,String prefix) {
return loadConfig(tClass,prefix,"");
}
public static <T> T loadConfig(Class<T> tClass,String prefix,String environment) {
StringBuilder configFileBuilder = new StringBuilder("application");
if (StrUtil.isNotBlank(environment)) {
configFileBuilder.append("-").append(environment);
}
configFileBuilder.append(".properties");
Props props = new Props(configFileBuilder.toString());
return props.toBean(tClass,prefix);
}
}
RpcApplication
类作为 RPC 框架配置访问入口
这里我们对全局配置对象 RpcConfig
使用单例模式实现,不用每次使用配置时都重新读取配置并创建对象,减少性能开销。
@Slf4j
public class RpcApplication {
private static volatile RpcConfig rpcConfig;
/**
* 框架初始化,支持传入自定义配置
* @param newRpcConfig
*/
public static void init(RpcConfig newRpcConfig) {
rpcConfig = newRpcConfig;
log.info("RpcApplication init...,config = {}",newRpcConfig.toString());
}
/**
* 初始化
*/
public static void init() {
RpcConfig newRpcConfig;
try {
newRpcConfig = ConfigUtils.loadConfig(RpcConfig.class, RpcConstant.DEFAULT_CONFIG_PREFIX);
}catch (Exception e) {
newRpcConfig = new RpcConfig();
}
init(newRpcConfig);
}
/**
* 获取配置
* @return
*/
public static RpcConfig getRpcConfig() {
if (rpcConfig == null) {
synchronized (RpcApplication.class) {
if (rpcConfig == null) {
init();
}
}
}
return rpcConfig;
}
}
application.properties
配置文件
根据编写的 RpcConfig
类和配置加载工具类,我们就可以像 Spring 一样从 application.properties
文件中读取配置了。不过现在只能读取 properties
格式文件的,并且在 RpcConfig
中定义的配置项,后续可以考虑扩展,像 Spring 那样可以读取 yml
格式的配置文件
application.properties
文件
rpc.name=t-rpc
rpc.version=2.0
rpc.serverPort=8081
rpc.serializer=kryo