dremio jdbc arp 扩展包装以及加载处理

如果按照官方直接提供的jdbc 存储插件进行jdbc驱动开发是很痛苦的,好多问题需要解决
还好官方抽象了arp 开发模式,大大简化了我们的处理,而且很灵活,很简单

参考处理

  • 创建调用链
    以下是一个添加arp 的处理流程
 
stack  com.dremio.exec.store.jdbc.conf.JdbcConf newPlugin
Press Q or Ctrl+C to abort.
Affect(class count: 8 , method count: 2) cost in 370 ms, listenerId: 2
ts=2022-03-03 13:44:05;thread_name=qtp114593564-209;id=d1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@18b4aac2
    @com.dremio.exec.store.jdbc.conf.JdbcConf.newPlugin()
        at com.dremio.exec.catalog.ManagedStoragePlugin.<init>(ManagedStoragePlugin.java:163)
        at com.dremio.exec.catalog.PluginsManager.newManagedStoragePlugin(PluginsManager.java:282)
        at com.dremio.exec.catalog.PluginsManager.newPlugin(PluginsManager.java:268)
        at com.dremio.exec.catalog.PluginsManager.create(PluginsManager.java:168)
        at com.dremio.exec.catalog.CatalogServiceImpl.createSource(CatalogServiceImpl.java:418)
        at com.dremio.exec.catalog.CatalogServiceImpl.access$400(CatalogServiceImpl.java:106)
        at com.dremio.exec.catalog.CatalogServiceImpl$SourceModifier.createSource(CatalogServiceImpl.java:751)
        at com.dremio.exec.catalog.CatalogImpl.createSource(CatalogImpl.java:1104)
        at com.dremio.exec.catalog.SourceAccessChecker.createSource(SourceAccessChecker.java:309)
        at com.dremio.exec.catalog.DelegatingCatalog.createSource(DelegatingCatalog.java:277)
        at com.dremio.dac.service.source.SourceService.registerSourceWithRuntime(SourceService.java:162)
        at com.dremio.dac.service.source.SourceService.registerSourceWithRuntime(SourceService.java:153)
        at com.dremio.dac.service.source.SourceService.registerSourceWithRuntime(SourceService.java:149)
        at com.dremio.dac.resource.PutSourceResource.putSource(PutSourceResource.java:80)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52)
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:124)
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:167)
        at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:219)
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:79)
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:469)
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:391)
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:80)
        at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:253)
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
        at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)
        at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:232)
        at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:680)
        at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:394)
        at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:366)
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:319)
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
        at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:799)
        at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1626)
        at com.dremio.dac.server.GenericResponseHeadersFilter.doFilter(GenericResponseHeadersFilter.java:46)
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601)
        at com.dremio.dac.server.SecurityHeadersFilter.doFilter(SecurityHeadersFilter.java:69)
        at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
        at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1601)
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:548)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1434)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:501)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1349)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
        at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:713)
        at org.eclipse.jetty.server.handler.RequestLogHandler.handle(RequestLogHandler.java:54)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
        at org.eclipse.jetty.server.Server.handle(Server.java:516)
        at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:388)
        at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:633)
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:380)
        at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277)
        at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
        at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
        at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:386)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883)
        at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034)
        at java.lang.Thread.run(Thread.java:750)
 
  • arp 扩展处理
    JdbcConf 抽象类,我们实际扩展的是AbstractArpConf
 
public abstract class JdbcConf<T extends DialectConf<T, JdbcStoragePlugin>> extends DialectConf<T, JdbcStoragePlugin> {
    private static final Logger logger = LoggerFactory.getLogger(JdbcConf.class);
 
    public JdbcConf() {
    }
   // 抽象方法,简化arp开发, 包含了三个参数,JdbcPluginConfig builder ,CredentialsService 主要是特定的,目前主要看到了aws 的
OptionManager 是一个配置管理,可以获取系统配置参数
    public abstract JdbcPluginConfig buildPluginConfig(Builder var1, CredentialsService var2, OptionManager var3);
 
    public JdbcStoragePlugin newPlugin(SabotContext context, String name, Provider<StoragePluginId> pluginIdProvider) {
        JdbcSchemaFetcherFactory factory = JdbcSchemaFetcherFactory.of(context.getConfig(), context.getJdbcSchemaFetcherFactoryContext());
        logger.debug("Plugin {} is using fetcher factory: {}", name, factory.getClass());
        JdbcSchemaFetcher schemaFetcher = factory.newFetcher(name, this);
         // 基于配置创建jdbc 存储插件
        return new JdbcStoragePlugin(schemaFetcher.getConfig(), schemaFetcher, context.getConfig(), pluginIdProvider, context.getOptionManager().getOption(PlannerSettings.FULL_NESTED_SCHEMA_SUPPORT));
    }
}

AbstractArpConf 定义

public abstract class AbstractArpConf<T extends JdbcConf<T>> extends JdbcConf<T> {
    private static final Logger logger = LoggerFactory.getLogger(AbstractArpConf.class);
 
    public AbstractArpConf() {
    }
 
    protected static <T extends ArpDialect> T loadArpFile(String pathToArpFile, Function<ArpYaml, T> dialectConstructor) {
        ArpDialect dialect;
        try {
            ArpYaml yaml = ArpYaml.createFromFile(pathToArpFile);
            dialect = (ArpDialect)dialectConstructor.apply(yaml);
        } catch (Exception var4) {
            dialect = null;
            logger.error("Error creating dialect from ARP file {}.", pathToArpFile, var4);
        }
 
        return dialect;
    }
}

arp 机制

实际上dremio 实现了一个自己的插件管理器PluginsManager ,插件管理器是在
sabot/kernel/src/main/java/com/dremio/exec/catalog/CatalogServiceImpl.java 实现中创建的
创建方法(CatalogServiceImpl start 中创建的)

 
protected PluginsManager newPluginsManager() {
return new PluginsManager(context.get(), systemNamespace, datasetListingService.get(), optionManager.get(),
  config, sourceDataStore, scheduler.get(), connectionReaderProvider.get(), monitor, broadcasterProvider,
  isInfluxSource, modifiableSchedulerService);
}

PluginsManager 方法

 

 

PluginsManager 的create 方法会返回一个ManagedStoragePlugin,ManagedStoragePlugin 进行arp 扩展的创建加载,ManagedStoragePlugin 对象
的构造函数会创建arp 插件(可以结合上边的调用链查看)
sabot/kernel/src/main/java/com/dremio/exec/catalog/ManagedStoragePlugin.java

 
 public ManagedStoragePlugin(
      SabotContext context,
      Executor executor,
      boolean isMaster,
      ModifiableSchedulerService modifiableScheduler,
      NamespaceService systemUserNamespaceService,
      LegacyKVStore<NamespaceKey, SourceInternalData> sourceDataStore,
      SourceConfig sourceConfig,
      OptionManager options,
      ConnectionReader reader,
      CatalogServiceMonitor monitor,
      Provider<MetadataRefreshInfoBroadcaster> broadcasterProvider
  ) {
    this.rwlock = new ReentrantReadWriteLock(true);
    this.executor = executor;
    this.readLock = rwlock.readLock();
    this.writeLock = rwlock.writeLock();
    this.context = context;
    this.sourceConfig = sourceConfig;
    this.sourceKey = new NamespaceKey(sourceConfig.getName());
    this.name = sourceConfig.getName();
    this.systemUserNamespaceService = systemUserNamespaceService;
   // reader 是比较重要的,包含了一个默认实现ConnectionReaderImpl,基于bean 注入
    this.conf = reader.getConnectionConf(sourceConfig);
    // 此处创建jdbc 存储扩展
    this.plugin = conf.newPlugin(context, sourceConfig.getName(), this::getId);
    this.metadataPolicy = sourceConfig.getMetadataPolicy() == null ? CatalogService.NEVER_REFRESH_POLICY : sourceConfig.getMetadataPolicy();
    this.permissionsCache = new PermissionCheckCache(this::getPlugin, () -> getMetadataPolicy().getAuthTtlMs(), 2500);
    this.options = options;
    this.reader = reader;
    this.monitor = monitor;
 
    fixFailedThread = new FixFailedToStart();
    // leaks this so do last.
    this.metadataManager = new SourceMetadataManager(
        sourceKey,
        modifiableScheduler,
        isMaster,
        sourceDataStore,
        new MetadataBridge(),
        options,
        monitor,
        broadcasterProvider);
  }

说明

jdbc arp 的加载实际上是一种先创建,在使用的模式,加载处理上并没有太多的难度,主要是dremio 的包装比价方便,比较灵活,实际上还包含
jdbc 存储插件的配置存储,上边没有介绍,可以结合源码学习

posted on 2022-03-03 23:25  荣锋亮  阅读(72)  评论(0编辑  收藏  举报

导航