👆 这是第 352 篇不掺水的原创,想要了解更多,请戳下方卡片关注我们吧~
根据官网描述,Trino 是一个快速的、分布式的大数据查询引擎,支持单数据源查询及多数据源的联邦查询,且内置支持多种数据源,如 Hive
、MySQL
、Kafka
、Clickhouse
、Elasticsearch
等。Trino 基于 Java SPI 提供了一套优秀的插件体系,并开放了非常丰富的扩展点,供用户开发自定义插件以满足特定需求,如审计日志、权限控制等。
Trino 的插件是基于 Java 标准 SPI 机制实现,插件类配置在 META-INF/services
目录中,通过 Java ServiceLoader
加载。Java 的 SPI 机制在此不赘述。
Trino 定义了一个统一的插件接口类 Plugin
,不同的插件都需要实现该类。Plugin
接口提供了获取各类插件的入口方法。其代码结构如下:
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 插件的依赖:
<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
集合。
public class CustomAccessControlPlugin implements Plugin {
@Override
public Iterable<SystemAccessControlFactory> getSystemAccessControlFactories() {
return ImmutableList.of(new CustomAccessControlFactory());
}
}
2、SystemAccessControlFactory
是 Trino 用来创建权限控制插件的工厂类,所以我们继续定义一个类来实现 SystemAccessControlFactory
接口。
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 操作。
支持数据行过滤、列掩码等功能。
验证用户是否可以读写系统属性等等。
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
文件。编辑文件,添加如下配置:
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
指定多个配置文件,如下:
access-control.config-files = etc/access-control-1.properties, etc/access-control-2.properties
综上所述,我们已经完成了 Trino 插件的开发和部署,启动 Trino 后,可以在控制台查看日志确定插件是否已经安装成功。
Trino官方文档(https://trino.io/docs/current/)
如果你觉得这篇内容对你挺有启发,我想邀请你帮我两件小事
1.点个「在看」,让更多人也能看到这篇内容(点了「在看」,bug -1 😊)
招贤纳士
政采云技术团队(Zero),Base 杭州,一个富有激情和技术匠心精神的成长型团队。规模 500 人左右,在日常业务开发之外,还分别在云原生、区块链、人工智能、低代码平台、中间件、大数据、物料体系、工程平台、性能体验、可视化等领域进行技术探索和实践,推动并落地了一系列的内部技术产品,持续探索技术的新边界。此外,团队还纷纷投身社区建设,目前已经是 google flutter、scikit-learn、Apache Dubbo、Apache Rocketmq、Apache Pulsar、CNCF Dapr、Apache DolphinScheduler、alibaba Seata 等众多优秀开源社区的贡献者。
如果你想改变一直被事折腾,希望开始折腾事;如果你想改变一直被告诫需要多些想法,却无从破局;如果你想改变你有能力去做成那个结果,却不需要你;如果你想改变你想做成的事需要一个团队去支撑,但没你带人的位置;如果你想改变本来悟性不错,但总是有那一层窗户纸的模糊……如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望参与到随着业务腾飞的过程,亲手推动一个有着深入的业务理解、完善的技术体系、技术创造价值、影响力外溢的技术团队的成长过程,我觉得我们该聊聊。任何时间,等着你写点什么,发给 zcy-tc@cai-inc.com