Trino 插件开发入门

前言

根据官网描述,Trino 是一个快速的、分布式的大数据查询引擎,支持单数据源查询及多数据源的联邦查询,且内置支持多种数据源,如 HiveMySQLKafkaClickhouseElasticsearch 等。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 也提供了 JacksonSlice 依赖包,这些包需要使用 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 权限控制类提供具体的权限控制功能,包含并不限于以下能力:

  • 校验用户是否可以执行查询等操作。
  • 校验用户是否可以对 catalogschematable 做访问、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 调用插件方法时传入了 tablecolumns 参数,table 的类型是 CatalogSchemaTableNameCatalogSchemaTableName 中包含了 catalogNameschemaNametableName 信息。SystemSecurityContext context 中携带了上下文信息,包含本次查询的 queryId,以及用户信息:userprincipalgroups 等。根据这些信息,我们可以结合权限控制需求,开发定制化的权限控制逻辑。
  • getRowFilters,对表做行级权限控制,返回一个 ViewExpression 集合,ViewExpression 中的 expression 字段为 SQL 过滤条件。
  • getColumnMasks,给字段加掩码,实际使用时,可以根据需求对该字段做加密、脱敏等处理。

插件更多的权限控制方法,可以参见 Trino 源码,这里不再延伸。

部署配置

部署

首先使用 maven 打包命令,打包一个插件 jar 包。

然后,在 Trino 安装路径下,找到 plugin 目录。Trino 的插件就放在这个目录中。在 plugin 目录下创建一个子目录 my-custom-access-control,名称和插件名称保持一致。在新建的目录中放入打包好的插件 jar 包,其他依赖包一并放入。虽然官网说明表示插件必须部署到 Trino 集群的所有节点中(coordinatorworkers),但实际部分插件只部署到 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 后,可以在控制台查看日志确定插件是否已经安装成功。

参考

Trino官方文档

推荐阅读

精准测试体系构建

操作日志数据治理实战

事务探索

Java 动态编译在项目中的实践

RocketMQ DLedger 初识

招贤纳士

政采云技术团队(Zero),Base 杭州,一个富有激情和技术匠心精神的成长型团队。规模 500 人左右,在日常业务开发之外,还分别在云原生、区块链、人工智能、低代码平台、中间件、大数据、物料体系、工程平台、性能体验、可视化等领域进行技术探索和实践,推动并落地了一系列的内部技术产品,持续探索技术的新边界。此外,团队还纷纷投身社区建设,目前已经是 google flutter、scikit-learn、Apache Dubbo、Apache Rocketmq、Apache Pulsar、CNCF Dapr、Apache DolphinScheduler、alibaba Seata 等众多优秀开源社区的贡献者。

如果你想改变一直被事折腾,希望开始折腾事;如果你想改变一直被告诫需要多些想法,却无从破局;如果你想改变你有能力去做成那个结果,却不需要你;如果你想改变你想做成的事需要一个团队去支撑,但没你带人的位置;如果你想改变本来悟性不错,但总是有那一层窗户纸的模糊......如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望参与到随着业务腾飞的过程,亲手推动一个有着深入的业务理解、完善的技术体系、技术创造价值、影响力外溢的技术团队的成长过程,我觉得我们该聊聊。任何时间,等着你写点什么,发给 zcy-tc@cai-inc.com

微信公众号

文章同步发布,政采云技术团队公众号,欢迎关注

相关推荐
WaaTong13 分钟前
《重学Java设计模式》之 原型模式
java·设计模式·原型模式
m0_7430484413 分钟前
初识Java EE和Spring Boot
java·java-ee
AskHarries15 分钟前
Java字节码增强库ByteBuddy
java·后端
小灰灰__35 分钟前
IDEA加载通义灵码插件及使用指南
java·ide·intellij-idea
夜雨翦春韭39 分钟前
Java中的动态代理
java·开发语言·aop·动态代理
程序媛小果1 小时前
基于java+SpringBoot+Vue的宠物咖啡馆平台设计与实现
java·vue.js·spring boot
追风林1 小时前
mac m1 docker本地部署canal 监听mysql的binglog日志
java·docker·mac
芒果披萨1 小时前
El表达式和JSTL
java·el
不能再留遗憾了2 小时前
RabbitMQ 高级特性——消息分发
分布式·rabbitmq·ruby
duration~2 小时前
Maven随笔
java·maven