SOFA RPC 源码解析
1、SOFA RPC 源码解析 —— 服务发布篇
从SOFA RPC 源码解析 —— 服务发布篇中来看有很多地方我都提到了SPI,那么什么是SPI呢,我们简单介绍下JAVA的SPI流程:JAVA的SPI运行流程是运用java.util.ServiceLoader这个类的load方法去在src/META-INF/services/寻找对应的全路径接口名称的文件,然后在文件中找到对应的实现方法并注入实现,然后你可以使用了。(点击JAVA SPI),话不多说,我们有了大概的spi的概念后就来看下SOFA RPC是怎么实现SPI的。
我们就从熟悉的代码开始吧:
public class RpcServer {
public static void main(String[] args) {
// 构建RegistryConfig 注册配置
RegistryConfig registryConfig = new RegistryConfig().setProtocol("zookeeper").setAddress("127.0.0.1:2181");
RegistryConfig registryConfig1 = new RegistryConfig().setProtocol("zookeeper").setAddress("127.0.0.1:2181");
List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
registryConfigs.add(registryConfig);
registryConfigs.add(registryConfig1);
// 构建ServerConfig 服务配置
List<ServerConfig> serverConfigs = new ArrayList<ServerConfig>();
ServerConfig serverConfig = new ServerConfig().setProtocol("bolt").setPort(12200).setDaemon(false);
ServerConfig serverConfig1 = new ServerConfig().setProtocol("rest").setPort(12200).setDaemon(false);
serverConfigs.add(serverConfig);
serverConfigs.add(serverConfig1);
// 构建发布配置
ProviderConfig<HelloService> providerConfig = new ProviderConfig<HelloService>().setApplication(new ApplicationConfig().setAppName("paul")).setInterfaceId(HelloService.class.getName()).setRef(new HelloServiceImpl()).setServer(serverConfigs).setRegistry(registryConfig);
// 正式发布
providerConfig.export();
}
}
上面那个代码就是我第一篇SOFA RPC 源码解析 —— 服务发布篇里面的,
我们再次简单分解下,就从第一步构建RegistryConfig 注册配置里面用到的SPI来讲:
点进去RegistryConfig的父类AbstractIdConfig
/**
* 默认配置带ID
*
* @param <S> the sub class of AbstractIdConfig
* @author <a href=mailto:zhanggeng.zg@antfin.com>GengZhang</a>
*/
public abstract class AbstractIdConfig<S extends AbstractIdConfig> implements Serializable {
private static final long serialVersionUID = -1932911135229369183L;
/**
* Id生成器
*/
private final static AtomicInteger ID_GENERATOR = new AtomicInteger(0);
static {
RpcRuntimeContext.now();
}
...
再点进去静态模块里的RpcRuntimeContext,找到:
static {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Welcome! Loading SOFA RPC Framework : {}, PID is:{}", Version.BUILD_VERSION, PID);
}
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"));
}
}
这里面的 ModuleFactory.installModules();就用到了SPI,根据配置加载扩展模块,一起来看看吧:
/**
* 加载全部模块
*/
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 = 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(mo