catalog的相关实现,通过CatalogManagerModule来做选择。更确切的说,是通过catalog.management配置项控制CatalogManagerConfig的catalogMangerKind做选择。catalog.management默认是STATIC。
image.png
这里主要有两个接口,ConnectorServicesProvider和CatalogManager。
ConnectorServicesProvider主要用来管理连接器功能,CatalogManager是用来管理Trino中所有Catalog的生命周期和交互。

ConnectorServicesProvider接口

loadInitialCatalogs方法

这个方法主要是负责从配置文件、数据库或者其他持久化存储中读取预定义的Catalog配置信息,然后创建并注册相应的Catalog对象到Trino的元数据管理器中,这个过程确保了Trino启动后可以直接识别和访问预先配置好的所有数据源。
这个方法的调用主要是在服务Server启动的时候。

StaticCatalogManager

StaticCatalogManager初始化时会读取StaticCatalogManagerConfig的配置信息,默认从etc/catalog/目录下,读取.properties结尾的文件。
比如这个目录下有一个文件叫mysql.properties,那这个文件对应的catalog就是去掉文件名后缀的名称,即mysql。这个catalog的属性,就是mysql.properties配置的相关信息。
StaticCatalogManager创建CatalogConnector的时候,
为了性能,这里也是采用多线程的方式。

executeUntilFailure(
    executor,
    catalogProperties.stream()
            .map(catalog -> (Callable<?>) () -> {
                String catalogName = catalog.getCatalogHandle().getCatalogName();
                log.info("-- Loading catalog %s --", catalogName);
                CatalogConnector newCatalog = catalogFactory.createCatalog(catalog);
                catalogs.put(catalogName, newCatalog);
                log.info("-- Added catalog %s using connector %s --", catalogName, catalog.getConnectorName());
                return null;
            })
            .collect(toImmutableList()));

创建CatalogConnector时,先获取ConnectorFactory,这个是插件加载时构建的。
createConnector中,会根据相应的类加载器,生成对应的Connector。
createCatalog中,会创建包括catalogHandle、connectorName、catalogConnector、informationSchemaConnector、systemConnector、catalogProperties的CatalogConnector。
这个CatalogConnector中就会有一个Catalog的成员变量。

  • catalogProperties是配置文件里的信息。
  • connectorName是catolog的名称,比如mysql。
  • catalogConnector、informationSchemaConnector、systemConnector都是ConnectorServices类型。
@Override
public CatalogConnector createCatalog(CatalogProperties catalogProperties)
{
    requireNonNull(catalogProperties, "catalogProperties is null");

    ConnectorFactory connectorFactory = connectorFactories.get(catalogProperties.getConnectorName());
    checkArgument(connectorFactory != null, "No factory for connector '%s'. Available factories: %s", catalogProperties.getConnectorName(), connectorFactories.keySet());

    Connector connector = createConnector(
            catalogProperties.getCatalogHandle().getCatalogName(),
            catalogProperties.getCatalogHandle(),
            connectorFactory,
            catalogProperties.getProperties());

    return createCatalog(
            catalogProperties.getCatalogHandle(),
            catalogProperties.getConnectorName(),
            connector,
            Optional.of(catalogProperties));
}

CoordinatorDynamicCatalogManager

CoordinatorDynamicCatalogManager初始化的时候,会先注入CatalogStore,CatalogStore包括InMemoryCatalogStore和FileCatalogStore,代表Catalog存储的不同介质。
FileCatalogStore的方式和STATIC一样,都是默认从etc/catalog/目录下,读取.properties结尾的文件。最终生成catalog和FileStoredCatalog映射的catalogs。
CoordinatorDynamicCatalogManager在调用loadInitialCatalogs的时候,会catalogStore中取catalog的信息,其他流程同StaticCatalogManager。

executeUntilFailure(
    executor,
    catalogStore.getCatalogs().stream()
            .map(storedCatalog -> (Callable<?>) () -> {
                CatalogProperties catalog = null;
                try {
                    catalog = storedCatalog.loadProperties();
                    CatalogConnector newCatalog = catalogFactory.createCatalog(catalog);
                    activeCatalogs.put(catalog.getCatalogHandle().getCatalogName(), newCatalog.getCatalog());
                    allCatalogs.put(catalog.getCatalogHandle(), newCatalog);
                    log.info("-- Added catalog %s using connector %s --", storedCatalog.getName(), catalog.getConnectorName());
                }
                catch (Throwable e) {
                    CatalogHandle catalogHandle = catalog != null ? catalog.getCatalogHandle() : createRootCatalogHandle(storedCatalog.getName(), new CatalogVersion("failed"));
                    ConnectorName connectorName = catalog != null ? catalog.getConnectorName() : new ConnectorName("unknown");
                    activeCatalogs.put(storedCatalog.getName(), failedCatalog(storedCatalog.getName(), catalogHandle, connectorName));
                    log.error(e, "-- Failed to load catalog %s using connector %s --", storedCatalog.getName(), connectorName);
                }
                return null;
            })
            .collect(toImmutableList()));

WorkerDynamicCatalogManager

WorkerDynamicCatalogManager的catalog信息是Coordinaor节点给的,所以他初始化的时候不做任何事。

ensureCatalogsLoaded

这个方法主要确保catalogs都已经成功加载。

StaticCatalogManager

StaticCatalogManager由于是直接读取文件的,所以如果不在内存中,就直接抛异常。

public void ensureCatalogsLoaded(Session session, List<CatalogProperties> catalogs)
{
    List<CatalogProperties> missingCatalogs = catalogs.stream()
            .filter(catalog -> !this.catalogs.containsKey(catalog.getCatalogHandle().getCatalogName()))
            .collect(toImmutableList());

    if (!missingCatalogs.isEmpty()) {
        throw new TrinoException(CATALOG_NOT_AVAILABLE, "Missing catalogs: " + missingCatalogs);
    }
}

CoordinatorDynamicCatalogManager

Coordinator如果发现不存在也是抛异常。

public void ensureCatalogsLoaded(Session session, List<CatalogProperties> catalogs)
{
    List<CatalogProperties> missingCatalogs = catalogs.stream()
            .filter(catalog -> !allCatalogs.containsKey(catalog.getCatalogHandle()))
            .collect(toImmutableList());

    if (!missingCatalogs.isEmpty()) {
        throw new TrinoException(CATALOG_NOT_AVAILABLE, "Missing catalogs: " + missingCatalogs);
    }
}

WorkerDynamicCatalogManager

WorkerDynamicCatalogManager是有没有的情况的,所以他不会抛异常,而是通过catalogFactory去创建CatalogConnector。

public void ensureCatalogsLoaded(Session session, List<CatalogProperties> expectedCatalogs)
{
    if (getMissingCatalogs(expectedCatalogs).isEmpty()) {
        return;
    }

    catalogsUpdateLock.lock();
    try {
        if (stopped) {
            return;
        }

        for (CatalogProperties catalog : getMissingCatalogs(expectedCatalogs)) {
            checkArgument(!catalog.getCatalogHandle().equals(GlobalSystemConnector.CATALOG_HANDLE), "Global system catalog not registered");
            CatalogConnector newCatalog = catalogFactory.createCatalog(catalog);
            catalogs.put(catalog.getCatalogHandle(), newCatalog);
            log.debug("Added catalog: " + catalog.getCatalogHandle());
        }
    }
    finally {
        catalogsUpdateLock.unlock();
    }
}

pruneCatalogs

这个方法主要是清理或筛选不再需要或无效的Catalogs。

StaticCatalogManager

由于静态的,意味着它们在系统启动时就已经固定设置好,不会在运行时动态添加、更新或删除。

CoordinatorDynamicCatalogManager和WorkerDynamicCatalogManager

这两个就会计算去移除Catalogs。

for (CatalogConnector removedCatalog : removedCatalogs) {
    try {
        removedCatalog.shutdown();
    }
    catch (Throwable e) {
        log.error(e, "Error shutting down catalog: %s".formatted(removedCatalog));
    }
}

CatalogManager

这里只有StaticCatalogManager和CoordinatorDynamicCatalogManager才需要管理catalog。

getCatalogProperties

获取catalog的信息,在封装Fragmenter的时候调用,Fragmenter是在调度的时候用于传给worker节点的信息。
在STATIC中,返回的是空信息。默认从本地文件读取catalog信息,它不会自动地将Catalog的配置信息从一台机器同步到另一台机器。每台机器上的Catalog配置是独立的,不会在集群内的不同节点间进行动态更新或共享。
而在CoordinatorDynamicCatalogManager中,会把自己的信息给worker,所以会把自己的allCatalogs返回来进行过滤,把对应的catalog信息传给worker。


大军
847 声望183 粉丝

学而不思则罔,思而不学则殆


引用和评论

0 条评论