前言
根据官网描述,Trino 是一个快速的、分布式的大数据查询引擎,支持单数据源查询及多数据源的联邦查询,且内置支持多种数据源,如 Hive
、MySQL
、Kafka
、Clickhouse
、Elasticsearch
等。Trino 基于 Java SPI 提供了一套优秀的插件体系,并开放了非常丰富的扩展点,供用户开发自定义插件以满足特定需求,如审计日志、权限控制等。
插件介绍
Trino 的插件是基于 Java 标准 SPI 机制实现,插件类配置在 META-INF/services
目录中,通过 Java ServiceLoader
加载。Java 的 SPI 机制在此不赘述。
Trino 定义了一个统一的插件接口类 Plugin
,不同的插件都需要实现该类。Plugin
接口提供了获取各类插件的入口方法。其代码结构如下:
java
public interface Plugin
{
default Iterable<ConnectorFactory> getConnectorFactories()
{
return emptyList();
}
default Iterable<SystemAccessControlFactory> getSystemAccessControlFactories()
{
return emptyList();
}
default Iterable<EventListenerFactory> getEventListenerFactories()
{
return emptyList();
}
// 更多插件创建方法详见源码 ... ...
}
如 getEventListenerFactories()
方法提供了获取事件监听插件的入口方法,其提供了 EventListenerFactory
工厂类,当需要创建插件实例时,Trino 调用该工厂类创建。其他类型的插件同理。
Plugin
接口中的每一个方法会提供一个默认实现,默认实现返回一个空集合,此时不会创建插件实例。当我们需要开发一个新 Trino
插件时,按需实现 Plugin
接口中的方法。比如,需要自定义的事件插件时,则实现 getEventListenerFactories()
方法。
Trino 提供了多种插件来满足不同的场景,最常见的如 connector
插件,通过 connector
插件,我们可以开发一个自定义的数据源连接器。其他常用插件如:
SystemAccessControl
权限控制EventListener
事件监听Functions
自定义函数PasswordAuthenticator
密码验证
更多插件参见官网,这里不一一列举。
插件开发
下面以权限控制插件为例,来说明开发 Trino 自定义插件的过程,开发过程使用 maven 打包。
依赖配置
在插件项目中的 maven pom.xml
文件中加上 Trino 插件的依赖:
java
<dependency>
<groupId>io.trino</groupId>
<artifactId>trino-spi</artifactId>
<scope>provided</scope>
</dependency>
注:依赖的 scope 为 provided
。Trino 在运行时会提供该包的类,所以不需要打包到插件包中。另外 Trino 也提供了 Jackson
和 Slice
依赖包,这些包需要使用 Trino 提供的版本。开发过程中需要的其他依赖,则需要加入到插件中,Trino 使用单独的类加载器来隔离不同的插件类加载。
代码开发
1、自定义一个 Java 类来实现 Plugin 接口,由于是权限控制插件,需要实现接口中的 getSystemAccessControlFactories()
方法,该方法返回一个 SystemAccessControlFactory
集合。
java
public class CustomAccessControlPlugin implements Plugin {
@Override
public Iterable<SystemAccessControlFactory> getSystemAccessControlFactories() {
return ImmutableList.of(new CustomAccessControlFactory());
}
}
2、SystemAccessControlFactory
是 Trino 用来创建权限控制插件的工厂类,所以我们继续定义一个类来实现 SystemAccessControlFactory
接口。 java
typescript
public class CustomAccessControlFactory implements SystemAccessControlFactory {
@Override
public String getName() {
return "my-custom-access-control";
}
@Override
public SystemAccessControl create(Map<String, String> config) {
return new CustomTableAccessControl(config);
}
}
该类需要实现两个方法:
getName()
返回插件名称,必须唯一。create()
返回自定义的权限控制类SystemAccessControl
。其传参Map<String, String> config
中的值以KeyValue
形式配置在权限配置文件中。
3、SystemAccessControl
权限控制类提供具体的权限控制功能,包含并不限于以下能力:
- 校验用户是否可以执行查询等操作。
- 校验用户是否可以对
catalog
、schema
、table
做访问、DML、DDL 操作。 - 支持数据行过滤、列掩码等功能。
- 验证用户是否可以读写系统属性等等。
java
public interface SystemAccessControl
{
default void checkCanSelectFromColumns(SystemSecurityContext context, CatalogSchemaTableName table, Set<String> columns)
{
denySelectColumns(table.toString(), columns);
}
default List<ViewExpression> getRowFilters(SystemSecurityContext context, CatalogSchemaTableName tableName)
{
return List.of();
}
default List<ViewExpression> getColumnMasks(SystemSecurityContext context, CatalogSchemaTableName tableName, String columnName, Type type)
{
return List.of();
}
// 更多权限控制方法详见源码 ... ...
}
代码示例中我们例举了几个权限控制方法:
checkCanSelectFromColumns
,校验用户是否可以从某张表中查询某些字段,从方法参数可以看到,Trino 调用插件方法时传入了table
和columns
参数,table
的类型是CatalogSchemaTableName
,CatalogSchemaTableName
中包含了catalogName
、schemaName
、tableName
信息。SystemSecurityContext context
中携带了上下文信息,包含本次查询的queryId
,以及用户信息:user
、principal
、groups
等。根据这些信息,我们可以结合权限控制需求,开发定制化的权限控制逻辑。getRowFilters
,对表做行级权限控制,返回一个ViewExpression
集合,ViewExpression
中的expression
字段为 SQL 过滤条件。getColumnMasks
,给字段加掩码,实际使用时,可以根据需求对该字段做加密、脱敏等处理。
插件更多的权限控制方法,可以参见 Trino 源码,这里不再延伸。
部署配置
部署
首先使用 maven 打包命令,打包一个插件 jar 包。
然后,在 Trino 安装路径下,找到 plugin
目录。Trino 的插件就放在这个目录中。在 plugin
目录下创建一个子目录 my-custom-access-control
,名称和插件名称保持一致。在新建的目录中放入打包好的插件 jar 包,其他依赖包一并放入。虽然官网说明表示插件必须部署到 Trino 集群的所有节点中(coordinator
和 workers
),但实际部分插件只部署到 coordinator
节点也可以,所以实际可按需部署。
配置
插件部署后,还需要在 Trino 集群的节点添加插件配置文件才会生效。Trino 配置文件放在安装目录下的 etc
目录中。以权限控制插件为例,默认的插件配置文件名称为 access-control.properties
,在 etc
目录中创建 access-control.properties
文件。编辑文件,添加如下配置:
java
access-control.name = my-custom-access-control
custom-property1 = custom-value1
custom-property2 = custom-value2
Trino 会根据 access-control.name
配置的值查找插件,所以需要和 SystemAccessControlFactory.getName()
方法的返回值保持一致。除了 access-control.name
之外的自定义配置都会通过 Map<String, String> config
传入到 SystemAccessControlFactory.create()
方法中,以供在插件中使用。
Trino 支持配置多个权限控制插件,可以在 etc/config.properties
文件中,添加 access-control.config-files
指定多个配置文件,如下:
java
access-control.config-files = etc/access-control-1.properties, etc/access-control-2.properties
总结
综上所述,我们已经完成了 Trino 插件的开发和部署,启动 Trino 后,可以在控制台查看日志确定插件是否已经安装成功。
参考
推荐阅读
招贤纳士
政采云技术团队(Zero),Base 杭州,一个富有激情和技术匠心精神的成长型团队。规模 500 人左右,在日常业务开发之外,还分别在云原生、区块链、人工智能、低代码平台、中间件、大数据、物料体系、工程平台、性能体验、可视化等领域进行技术探索和实践,推动并落地了一系列的内部技术产品,持续探索技术的新边界。此外,团队还纷纷投身社区建设,目前已经是 google flutter、scikit-learn、Apache Dubbo、Apache Rocketmq、Apache Pulsar、CNCF Dapr、Apache DolphinScheduler、alibaba Seata 等众多优秀开源社区的贡献者。
如果你想改变一直被事折腾,希望开始折腾事;如果你想改变一直被告诫需要多些想法,却无从破局;如果你想改变你有能力去做成那个结果,却不需要你;如果你想改变你想做成的事需要一个团队去支撑,但没你带人的位置;如果你想改变本来悟性不错,但总是有那一层窗户纸的模糊......如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望参与到随着业务腾飞的过程,亲手推动一个有着深入的业务理解、完善的技术体系、技术创造价值、影响力外溢的技术团队的成长过程,我觉得我们该聊聊。任何时间,等着你写点什么,发给 zcy-tc@cai-inc.com
微信公众号
文章同步发布,政采云技术团队公众号,欢迎关注