Trino 插件開發入門
前言
根據官網描述,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
插件,我們可以開發一個自定義的數據源連接器。其他常用插件如:
更多插件參見官網,這裏不一一列舉。
插件開發
下面以權限控制插件爲例,來說明開發 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/)
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/n5-CkF8rYRjqGWMEh1PvkQ