catalog的相关实现,通过CatalogManagerModule来做选择。更确切的说,是通过catalog.management配置项控制CatalogManagerConfig的catalogMangerKind做选择。catalog.management默认是STATIC。
这里主要有两个接口,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。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。