dremio ui 数据源插件加载处理简单说明
dremio 开发数据源扩展,基本包含了数据库,元数据类的,对象存储的,以及catalog 的,实际上开发扩展不算太难
默认开发的扩展直接放jars 文件夹就可以了,但是目前新版本我们会发现隐藏了一个opensearch 的插件,这个插件需
要通过配置开启,plugins.jdbc.opensearch.enabled
默认为false,开启之后界面就可以看到了
一些问题
实际上按照官方插件的开发机制,并没有说我们的插件如何显示,opensearch 是如何进行隐藏的
加载处理
实际上官方的处理比较简单,就是一些插件希望通过配置显示,那就使用一个配置,同时加载插件的时候基于配置选项过滤就可以了
- 参考调用链
- 参考处理
@GET
@RolesAllowed({"admin", "user"})
@Path("/type")
public ResponseList<SourceTypeTemplate> getSourceTypes() {
final ConnectionReader connectionReader = sabotContext.getConnectionReaderProvider().get();
final ResponseList<SourceTypeTemplate> types = new ResponseList<>();
for(Class<? extends ConnectionConf<?, ?>> input : connectionReader.getAllConnectionConfs().values()) {
// We can't use isInternal as it's not a static method, instead we only show listable sources.
if (isListable(input)) {
String sourceType = input.getAnnotation(SourceType.class).value();
// 此处进行了过滤处理
if (isSourceTypeVisible(sourceType) &&
sabotContext
.getSourceVerifierProvider()
.get()
.isSourceSupported(sourceType, sabotContext.getSystemOptionManager())) {
types.add(SourceTypeTemplate.fromSourceClass(input, false));
}
}
}
return types;
}
isSourceTypeVisible 处理 (实际上就是一个硬编码,同时结合配置参数)
private boolean isSourceTypeVisible(String sourceType) {
if ("HIVE".equals(sourceType)) {
return sabotContext.getOptionManager().getOption(ALLOW_HIVE_SOURCE);
}
if ("OPENSEARCH".equals(sourceType)) {
return sabotContext.getOptionManager().getOption(JDBC_OPENSEARCH_ENABLED);
}
if ("NESSIE".equals(sourceType)) {
return sabotContext.getOptionManager().getOption(NESSIE_PLUGIN_ENABLED);
}
return true;
}
ConnectionReader中source 插件的处理会调用ConnectionReaderImpl 中的getCandidateSources 实现(获取候选实现)
public static ConnectionReader makeReader(ScanResult scanResult) {
Collection<Class<? extends ConnectionConf<?, ?>>> sourceCandidates = getCandidateSources(scanResult);
ImmutableMap.Builder<String, Schema<? extends ConnectionConf<?, ?>>> stringMap = ImmutableMap.builder();
for (Class<? extends ConnectionConf<?, ?>> input : sourceCandidates) {
SourceType type = input.getAnnotation(SourceType.class);
try {
Schema<? extends ConnectionConf<?, ?>> schema = ConnectionSchema.getSchema(input);
stringMap.put(type.value(), schema);
} catch(Exception ex) {
throw new RuntimeException("failure trying to read source conf: " + input.getName(), ex);
}
}
return new ConnectionReaderImpl(stringMap.build());
}
查找插件部分(核心在ConnectionReaderImpl 中)
protected static Collection<Class<? extends ConnectionConf<?, ?>>> getCandidateSources(ScanResult scanResult) {
ImmutableList.Builder<Class<? extends ConnectionConf<?, ?>>> candidates = new ImmutableList.Builder<>();
// 通过类扫描处理,核心是SourceType 注解
for(Class<?> input : scanResult.getAnnotatedClasses(SourceType.class)) {
try {
if (Modifier.isAbstract(input.getModifiers())
|| Modifier.isInterface(input.getModifiers())
|| !ConnectionConf.class.isAssignableFrom(input)) {
logger.warn("Failure trying to recognize SourceConf for {}. Expected a concrete implementation of SourceConf.", input.getName());
continue;
}
} catch (Exception e) {
logger.warn("Failure trying to recognize SourceConf for {}", input.getName(), e);
continue;
}
// Check done just above
candidates.add((Class<? extends ConnectionConf<?, ?>>) input);
}
return candidates.build();
}
页面显示(SourceTypeTemplate.fromSourceClass 转换为方便显示的)
说明
以上是一个简单的说明,实际上我们经常在dremio 的代码中可以看到配置参数的使用,有些感觉比较怪,明显没有直接调用的地方,但是就是有作用
可以结合一些够工具方便分析下,以上就是社区版ce 插件中opensearch 加载的一些说明
参考资料
https://docs.dremio.com/current/sonar/data-sources/
dac/backend/src/main/java/com/dremio/dac/api/DepreciatedSourceResource.java
sabot/kernel/src/main/java/com/dremio/exec/catalog/ConnectionReader.java
sabot/kernel/src/main/java/com/dremio/exec/server/SabotContext.java
sabot/kernel/src/main/java/com/dremio/exec/catalog/ConnectionReaderImpl.java
dac/backend/src/main/java/com/dremio/dac/api/SourceTypeTemplate.java