Linkis實踐——新引擎實現流程解析

語言: CN / TW / HK

目錄導讀

  • 1. Linkis 新引擎功能程式碼實現

    • 1.1 新建一個 maven 模組,並引入 ECP 的 maven 依賴

    • 1.2 實現 ECP 的主要介面

    • 1.3 實現引擎 Executor 執行器邏輯

    • 1.4 引擎功能實現的實際案例

  • 2. 以實際擴充套件引擎為例詳解新引擎實現的後續步驟

    • 2.1 引擎程式碼準備

    • 2.2 新引擎型別擴充套件

    • 2.3 Kyuubi 引擎標籤中的版本號設定

    • 2.4 允許 Scripts 中開啟 kyuubi 型別的指令碼檔案

    • 2.5 配置 kyuubi 指令碼變數儲存和解析

    • 2.6 ujes.client 中增加新引擎型別

    • 2.7 Linkis 管理員臺介面引擎管理器中加入新增引擎文字提示或圖示

    • 2.8 引擎的編譯打包和安裝部署

    • 2.9 引擎資料庫配置

    • 2.10 DSS Scripts 中新增指令碼型別以及圖示等資訊

    • 2.11 DSS 的工作流適配

  • 3. 總結

目錄導讀

1. Linkis 新引擎功能程式碼實現

實現一個新的引擎其實就是實現一個新的 EngineConnPlugin(ECP)引擎外掛。具體步驟如下:

1.1 新建一個 maven 模組,並引入 ECP 的 maven 依賴

新引擎模組
<dependency>
<groupId>org.apache.linkis</groupId>
<artifactId>linkis-engineconn-plugin-core</artifactId>
<version>${linkis.version}</version>
</dependency>
<!-- 以及一些其他所需依賴的maven配置 -->

1.2 實現 ECP 的主要介面

  • EngineConnPlugin:啟動 EngineConn 時,先找到對應的 EngineConnPlugin 類,以此為入口,獲取其它核心介面的實現,是必須實現的主要介面。

  • EngineConnFactory:實現如何啟動一個引擎聯結器,和如何啟動一個引擎執行器的邏輯,是必須實現的介面。

    • 實現 createEngineConn 方法:返回一個 EngineConn 物件,其中,getEngine 返回一個封裝了與底層引擎連線資訊的物件,同時包含 Engine 型別資訊。

    • 對於只支援單一計算場景的引擎,繼承 SingleExecutorEngineConnFactory,實現 createExecutor,返回對應的 Executor。

    • 對於支援多計算場景的引擎,需要繼承 MultiExecutorEngineConnFactory,併為每種計算型別實現一個 ExecutorFactory。EngineConnPlugin 會通過反射獲取所有的 ExecutorFactory,根據實際情況返回對應的 Executor。

  • EngineConnResourceFactory:用於限定啟動一個引擎所需要的資源,引擎啟動前,將以此為依 據 向 Linkis Manager 申 請 資 源。非必須,預設可以使用 GenericEngineResourceFactory。

  • EngineLaunchBuilder:用於封裝 EngineConnManager 可以解析成啟動命令的必要資訊。非必須,可以直接繼承 JavaProcessEngineConnLaunchBuilder。

1.3 實現引擎 Executor 執行器邏輯

Executor 為執行器,作為真正的計算場景執行器,是實際的計算邏輯執行單元,也是對引擎各種具體能力的抽象,提供加鎖、訪問狀態、獲取日誌等多種不同的服務。並根據實際的使用需要,Linkis 預設提供以下的派生 Executor 基類,其類名和主要作用如下:

  • SensibleExecutor:

    • Executor 存在多種狀態,允許 Executor 切換狀態

    • Executor 切換狀態後,允許做通知等操作

  • YarnExecutor:指 Yarn 型別的引擎,能夠獲取得到 applicationId 和 applicationURL 和佇列。

  • ResourceExecutor:指引擎具備資源動態變化的能力,配合提供 requestExpectedResource 方法,用於每次希望更改資源時,先向 RM 申請新的資源;而 resourceUpdate 方法,用於每次引擎實際使用資源發生變化時,向 RM 彙報資源情況。

  • AccessibleExecutor:是一個非常重要的 Executor 基類。如果使用者的 Executor 繼承了該基類,則表示該 Engine 是可以被訪問的。這裡需區分 SensibleExecutor 的 state()和 AccessibleExecutor 的 getEngineStatus()方法:state()用於獲取引擎狀態,getEngineStatus()會獲取引擎的狀態、負載、併發等基礎指標 Metric 資料。

  • 同時,如果繼承了 AccessibleExecutor,會觸發 Engine 程序例項化多個 EngineReceiver 方法。EngineReceiver 用於處理 Entrance、EM 和 LinkisMaster 的 RPC 請求,使得該引擎變成了一個可被訪問的引擎,使用者如果有特殊的 RPC 需求,可以通過實現 RPCService 介面,進而實現與 AccessibleExecutor 通訊。

  • ExecutableExecutor:是一個常駐型的 Executor 基類,常駐型的 Executor 包含:生產中心的 Streaming 應用、提交給 Schedulis 後指定要以獨立模式執行的指令碼、業務使用者的業務應用等。

  • StreamingExecutor:Streaming 為流式應用,繼承自 ExecutableExecutor,需具備診斷、do checkpoint、採集作業資訊、監控告警的能力。

  • ComputationExecutor:是常用的互動式引擎 Executor,處理互動式執行任務,並且具備狀態查詢、任務 kill 等互動式能力。

1.4 引擎功能實現的實際案例

以下以 Hive 引擎為案例,說明各個介面的實現方式。

Hive 引擎是一個互動式引擎,因此在實現 Executor 時,繼承了 ComputationExecutor,並做 了以下 maven 依賴的引入:

<dependency>
<groupId>org.apache.linkis</groupId>
<artifactId>linkis-computation-engineconn</artifactId>
<version>${linkis.version}</version>
</dependency>

作為 ComputationExecutor 的子類,HiveEngineConnExecutor 實現了 executeLine 方法,該方法接收一行執行語句,呼叫 Hive 的介面進行執行後,返回不同的 ExecuteResponse 表示成功或失敗。同時在該方法中,通過引數 engineExecutorContext 中提供的介面,實現了結果集、日誌和進度的傳輸。

Hive 的引擎是隻需要執行 HQL 的 Executor,是一個單一執行器的引擎,因此,在定義 HiveEngineConnFactory 時,繼承的是 SingleExecutorEngineConnFactory,實現了以下兩個介面:

  • createEngineConn:建立了一個包含 UserGroupInformation、SessionState 和 HiveConf 的物件,作為與底層引擎的連線資訊的封裝,set 到 EngineConn 物件中返回。

  • createExecutor:根據當前的引擎連線資訊,建立一個 HiveEngineConnExecutor 執行器物件。

Hive 引擎是一個普通的 Java 程序,因此在實現 EngineConnLaunchBuilder 時,直接繼承了 JavaProcessEngineConnLaunchBuilder。像記憶體大小、Java 引數和 classPath,可以通過配置進行調整,具體參考 EnvConfiguration 類。

Hive 引擎使用的是 LoadInstanceResource 資源,因此不需要實現 EngineResourceFactory,直接使用預設的 GenericEngineResourceFactory,通過配置調整資源的數量,具體參考 EngineConnPluginConf 類。

實現 HiveEngineConnPlugin,提供以上實現類的建立方法。

2. 以實際擴充套件引擎為例詳解新引擎實現的後續步驟

本文以合合資訊內部維護的 Linkis 分支中增加的 Kyuubi 引擎舉例,補充說明使用者在擴充套件新引擎時,除關注引擎本身的核心功能之外,還需要的一些額外的配置或修改。Kyuubi 引擎在 Linkis 的官方分支上還未支援,可以使用 jdbc 引擎來連線 kyuubi 服務執行對應指令碼。

2.1 引擎程式碼準備

合合 Linkis 分支中 Kyuubi 引擎的程式碼實現比較簡單,是對 JDBC 引擎模組的一個拷貝。不太一樣的地方是,JDBC 引擎中的核心類 JDBCEngineConnExecutor 繼承的抽象類是 ConcurrentComputationExecutor ,Kyuubi 引擎中的核心類 KyuubiJDBCEngineConnExecutor 繼承的抽象類是 ComputationExecutor 。這導致兩者最大的一個區別是:JDBC 引擎例項由管理員使用者啟動,被所有使用者共享;而 Kyuubi 型別的指令碼提交時,每個使用者會各自啟動一個引擎例項,使用者間引擎例項互相隔離。其實針對 JDBC 型別的引擎,標準化的做法應該是使用併發引擎的特性,避免每個使用者拉起一個引擎例項,以提高機器的資源利用率,這個在此處暫不細說,因為無論是併發引擎還是計算引擎,下文提到的額外修改流程應是一致的。

相應的,如果你新增的引擎是併發引擎,那麼你需要關注下這個類:AMConfiguration.scala,如果你新增的引擎是計算類引擎,則可忽略。

object AMConfiguration {
// 如果你的引擎是多使用者併發引擎,那麼這個配置項需要關注下
val MULTI_USER_ENGINE_TYPES = CommonVars("wds.linkis.multi.user.engine.types", "jdbc,ck,es,io_file,appconn")

private def getDefaultMultiEngineUser(): String = {
// 此處應該是為了設定併發引擎拉起時的啟動使用者,預設jvmUser即是引擎服務Java程序的啟動使用者
val jvmUser = Utils.getJvmUser
s"""{jdbc:"$jvmUser", presto: "$jvmUser", kyuubi: "$jvmUser", es: "$jvmUser", ck:"$jvmUser", appconn:"$jvmUser", io_file:"root"}"""
}
}

2.2 新引擎型別擴充套件

實現 ComputationSingleExecutorEngineConnFactory 介面的類 KyuubiJDBCEngineConnFactory 中,下面兩個方法需要實現:

override protected def getEngineConnType: EngineType = EngineType.KYUUBI

override protected def getRunType: RunType = RunType.KYUUBI

因此需要在 EngineType 和 RunType 中增加 Kyuubi 對應的變數。

// EngineType中類似已存在引擎的變數定義,增加Kyuubi相關變數或程式碼
object EngineType extends Enumeration with Logging {
val KYUUBI = Value("kyuubi")
}

def mapStringToEngineType(str: String): EngineType = str match {
case _ if KYUUBI.toString.equalsIgnoreCase(str) => KYUUBI
}

// RunType中
object RunType extends Enumeration {
val KYUUBI = Value("kyuubi")
}

2.3 Kyuubi 引擎標籤中的版本號設定

// 在LabelCommonConfig中增加kyuubi的version配置
public class LabelCommonConfig {
public final static CommonVars<String> KYUUBI_ENGINE_VERSION = CommonVars.apply("wds.linkis.kyuubi.engine.version", "1.4");
}

// 在EngineTypeLabelCreator的init方法中補充kyuubi的匹配邏輯
// 如果這一步不做,程式碼提交到引擎上時,引擎標籤資訊中會缺少版本號
public class EngineTypeLabelCreator {
private static void init() {
defaultVersion.put(EngineType.KYUUBI().toString(), LabelCommonConfig.KYUUBI_ENGINE_VERSION.getValue());
}
}

2.4 允許 Scripts 中開啟 kyuubi 型別的指令碼檔案

在 fileType 陣列中增加新引擎指令碼型別,如果不加,Scripts 檔案列表中不允許開啟新引擎的指令碼型別

// FileSource.scala中
object FileSource {
private val fileType = Array("......", "kyuubi")
}

2.5 配置 kyuubi 指令碼變數儲存和解析

如果這個操作不做,新增引擎 kyuubi 的指令碼中變數不能被儲存和解析,指令碼中直接使用${變數}時程式碼會執行失敗!

指令碼變數

在 Linkis-1.0.3 版本之前:

// QLScriptCompaction.scala
class QLScriptCompaction private extends CommonScriptCompaction{
override def belongTo(suffix: String): Boolean = {
suffix match {
...
case "kyuubi" => true
case _ => false
}
}
}

// QLScriptParser.scala
class QLScriptParser private extends CommonScriptParser {
override def belongTo(suffix: String): Boolean = {
suffix match {
case "kyuubi" => true
case _ => false
}
}
}

// CustomVariableUtils.scala中
object CustomVariableUtils extends Logging {
def replaceCustomVar(jobRequest: JobRequest, runType: String): (Boolean, String) = {
runType match {
......
case "hql" | "sql" | "fql" | "jdbc" | "hive"| "psql" | "presto" | "ck" | "kyuubi" => codeType = SQL_TYPE
case _ => return (false, code)
}
}
}

在 Linkis-1.1.2 版本之後:

// 通過CodeAndRunTypeUtils工具類中的CODE_TYPE_AND_RUN_TYPE_RELATION變數來維護codeType和runType間的對應關係
val CODE_TYPE_AND_RUN_TYPE_RELATION = CommonVars("wds.linkis.codeType.runType.relation", "sql=>sql|hql|jdbc|hive|psql|fql|kyuubi,python=>python|py|pyspark,java=>java,scala=>scala,shell=>sh|shell")

參考 PR:https://github.com/apache/incubator-linkis/pull/2047

2.6 ujes.client 中增加新引擎型別

// JobExecuteAction.scala中

object EngineType {
......
val KYUUBI = new EngineType {
override val toString: String = "kyuubi"
val KYUUBI_RunType = new RunType {
override val toString: String = "kyuubi"
}
override def getDefaultRunType: RunType = KYUUBI_RunType
}
}

// UJESClientUtils.scala中
object UJESClientUtils {
def toEngineType(engineType: String): EngineType = engineType match {
......
case "kyuubi" => EngineType.KYUUBI
case _ => EngineType.SPARK
}

def toRunType(runType:String, engineType: EngineType) : RunType = runType match {
......
case "kyuuubi" => EngineType.KYUUBI.KYUUBI_RunType
case _ => EngineType.SPARK.SQL
}
}

客戶端 API 執行新引擎型別指令碼時所需。

2.7 Linkis 管理員臺介面引擎管理器中加入新增引擎文字提示或圖示

web/src/dss/module/resourceSimple/engine.vue

methods: {
calssifyName(params) {
switch (params) {
case 'kyuubi':
return 'Kyuubi';
......
}
}
// 圖示過濾
supportIcon(item) {
const supportTypes = [
......
{ rule: 'kyuubi', logo: 'fi-kyuubi' },
];
}
}

最終呈現給使用者的效果:

kyuubi引擎

2.8 引擎的編譯打包和安裝部署

新引擎模組編譯的示例命令如下:

cd /Users/leojie/intsig_project/intsiglinkis/linkis-engineconn-plugins/engineconn-plugins/kyuubi

mvn clean install -DskipTests

編譯完整專案時,新增引擎預設不會加到最終的 tar.gz 壓縮包中,如果需要,請修改如下檔案:

assembly-combined-package/assembly-combined/src/main/assembly/assembly.xml

<!--kyuubi-->
<fileSets>
......
<fileSet>
<directory>
../../linkis-engineconn-plugins/engineconn-plugins/kyuubi/target/out/
</directory>
<outputDirectory>lib/linkis-engineconn-plugins/</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
</fileSets>

然後對在專案根目錄執行編譯命令:

mvn clean install -DskipTests

編譯成功後在 assembly-combined-package/target/apache-linkis-1.x.x-incubating-bin.tar.gz 和 linkis-engineconn-plugins/engineconn-plugins/kyuubi/target/目錄下找到 out.zip。

上傳 out.zip 檔案到 Linkis 的部署節點,解壓縮到:安裝目錄/lib/linkis-engineconn-plugins/:

引擎安裝

解壓後別忘記刪除 out.zip,至此引擎編譯和安裝完成。

2.9 引擎資料庫配置

引擎安裝完之後,要想執行新的引擎程式碼,還需對引擎進行資料庫配置,以 Kyuubi 引擎為例,按照你自己實現的新引擎的情況,請按需修改。

SQL 參考如下:

SET @KYUUBI_LABEL="kyuubi-1.4";

SET @KYUUBI_ALL=CONCAT('*-*,',@KYUUBI_LABEL);
SET @KYUUBI_IDE=CONCAT('*-IDE,',@KYUUBI_LABEL);
SET @KYUUBI_NODE=CONCAT('*-nodeexecution,',@KYUUBI_LABEL);

-- kyuubi
INSERT INTO `linkis_ps_configuration_config_key` (`key`, `description`, `name`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`, `treeName`, `engine_conn_type`) VALUES ('wds.linkis.rm.instance', '範圍:1-20,單位:個', 'kyuubi引擎最大併發數', '2', 'NumInterval', '[1,20]', '0', '0', '1', '佇列資源', 'kyuubi');

insert into `linkis_ps_configuration_config_key` (`key`, `description`, `name`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`, `treeName`, `engine_conn_type`) VALUES ('wds.linkis.kyuubi.jdbc.connect.url', '例如:jdbc:hive2://127.0.0.1:10000', 'jdbc連線地址', '\"jdbc:hive2://127.0.0.1:10009/;[email protected]\"', 'None', '', '0', '0', '1', '資料來源配置', 'kyuubi');
insert into `linkis_ps_configuration_config_key` (`key`, `description`, `name`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`, `treeName`, `engine_conn_type`) VALUES ('wds.linkis.kyuubi.jdbc.version', '取值範圍:jdbc3,jdbc4', 'jdbc版本','jdbc4', 'OFT', '[\"jdbc3\",\"jdbc4\"]', '0', '0', '1', '資料來源配置', 'kyuubi');
insert into `linkis_ps_configuration_config_key` (`key`, `description`, `name`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`, `treeName`, `engine_conn_type`) VALUES ('wds.linkis.kyuubi.jdbc.connect.max', '範圍:1-20,單位:個', 'jdbc引擎最大連線數', '10', 'NumInterval', '[1,20]', '0', '0', '1', '資料來源配置', 'kyuubi');
insert into `linkis_ps_configuration_config_key` (`key`, `description`, `name`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`, `treeName`, `engine_conn_type`) VALUES ('wds.linkis.kyuubi.jdbc.auth.type', '取值範圍:SIMPLE,USERNAME,KERBEROS', 'jdbc認證方式', 'KERBEROS', 'OFT', '[\"SIMPLE\",\"USERNAME\",\"KERBEROS\"]', '0', '0', '1', '使用者配置', 'kyuubi');
insert into `linkis_ps_configuration_config_key` (`key`, `description`, `name`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`, `treeName`, `engine_conn_type`) VALUES ('wds.linkis.kyuubi.jdbc.username', 'username', '資料庫連線使用者名稱', '', 'None', '', '0', '0', '1', '使用者配置', 'kyuubi');
insert into `linkis_ps_configuration_config_key` (`key`, `description`, `name`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`, `treeName`, `engine_conn_type`) VALUES ('wds.linkis.kyuubi.jdbc.password', 'password', '資料庫連線密碼', '', 'None', '', '0', '0', '1', '使用者配置', 'kyuubi');
insert into `linkis_ps_configuration_config_key` (`key`, `description`, `name`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`, `treeName`, `engine_conn_type`) VALUES ('wds.linkis.kyuubi.jdbc.principal', '例如:hadoop/[email protected]', '使用者principal', 'hadoop/[email protected]', 'None', '', '0', '0', '1', '使用者配置', 'kyuubi');
insert into `linkis_ps_configuration_config_key` (`key`, `description`, `name`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`, `treeName`, `engine_conn_type`) VALUES ('wds.linkis.kyuubi.jdbc.keytab.location', '例如:/data/keytab/hadoop.keytab', '使用者keytab檔案路徑', '/data/keytab/hadoop.keytab', 'None', '', '0', '0', '1', '使用者配置', 'kyuubi');
insert into `linkis_ps_configuration_config_key` (`key`, `description`, `name`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`, `treeName`, `engine_conn_type`) VALUES ('wds.linkis.kyuubi.jdbc.proxy.user.property', '例如:hive.server2.proxy.user', '使用者代理配置', 'hive.server2.proxy.user', 'None', '', '0', '0', '1', '使用者配置', 'kyuubi');

INSERT INTO `linkis_ps_configuration_config_key` (`key`, `description`, `name`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`, `treeName`, `engine_conn_type`) VALUES ('wds.linkis.engineconn.java.driver.cores', '取值範圍:1-8,單位:個', 'kyuubi引擎初始化核心個數', '1', 'NumInterval', '[1,8]', '0', '0', '1', 'kyuubi引擎設定', 'kyuubi');
INSERT INTO `linkis_ps_configuration_config_key` (`key`, `description`, `name`, `default_value`, `validate_type`, `validate_range`, `is_hidden`, `is_advanced`, `level`, `treeName`, `engine_conn_type`) VALUES ('wds.linkis.engineconn.java.driver.memory', '取值範圍:1-8,單位:G', 'kyuubi引擎初始化記憶體大小', '1g', 'Regex', '^([1-8])(G|g)$', '0', '0', '1', 'kyuubi引擎設定', 'kyuubi');

insert into `linkis_cg_manager_label` (`label_key`, `label_value`, `label_feature`, `label_value_size`, `update_time`, `create_time`) VALUES ('combined_userCreator_engineType',@KYUUBI_ALL, 'OPTIONAL', 2, now(), now());


insert into `linkis_ps_configuration_key_engine_relation` (`config_key_id`, `engine_type_label_id`)
(select config.id as `config_key_id`, label.id AS `engine_type_label_id` FROM linkis_ps_configuration_config_key config INNER JOIN linkis_cg_manager_label label ON config.engine_conn_type = 'kyuubi' and label_value = @KYUUBI_ALL);

insert into `linkis_cg_manager_label` (`label_key`, `label_value`, `label_feature`, `label_value_size`, `update_time`, `create_time`) VALUES ('combined_userCreator_engineType',@KYUUBI_IDE, 'OPTIONAL', 2, now(), now());
insert into `linkis_cg_manager_label` (`label_key`, `label_value`, `label_feature`, `label_value_size`, `update_time`, `create_time`) VALUES ('combined_userCreator_engineType',@KYUUBI_NODE, 'OPTIONAL', 2, now(), now());


select @label_id := id from linkis_cg_manager_label where `label_value` = @KYUUBI_IDE;
insert into linkis_ps_configuration_category (`label_id`, `level`) VALUES (@label_id, 2);

select @label_id := id from linkis_cg_manager_label where `label_value` = @KYUUBI_NODE;
insert into linkis_ps_configuration_category (`label_id`, `level`) VALUES (@label_id, 2);

-- jdbc default configuration
insert into `linkis_ps_configuration_config_value` (`config_key_id`, `config_value`, `config_label_id`) (select `relation`.`config_key_id` AS `config_key_id`, '' AS `config_value`, `relation`.`engine_type_label_id` AS `config_label_id` FROM linkis_ps_configuration_key_engine_relation relation INNER JOIN linkis_cg_manager_label label ON relation.engine_type_label_id = label.id AND label.label_value = @KYUUBI_ALL);

如果想重置引擎的資料庫配置資料,參考檔案如下,請按需進行修改使用:

-- 清除kyuubi引擎的初始化資料
SET @KYUUBI_LABEL="kyuubi-1.4";

SET @KYUUBI_ALL=CONCAT('*-*,',@KYUUBI_LABEL);
SET @KYUUBI_IDE=CONCAT('*-IDE,',@KYUUBI_LABEL);
SET @KYUUBI_NODE=CONCAT('*-nodeexecution,',@KYUUBI_LABEL);

delete from `linkis_ps_configuration_config_value` where `config_label_id` in
(select `relation`.`engine_type_label_id` AS `config_label_id` FROM `linkis_ps_configuration_key_engine_relation` relation INNER JOIN `linkis_cg_manager_label` label ON relation.engine_type_label_id = label.id AND label.label_value = @KYUUBI_ALL);

delete from `linkis_ps_configuration_key_engine_relation`
where `engine_type_label_id` in
(select label.id FROM `linkis_ps_configuration_config_key` config
INNER JOIN `linkis_cg_manager_label` label
ON config.engine_conn_type = 'kyuubi' and label_value = @KYUUBI_ALL);


delete from `linkis_ps_configuration_category`
where `label_id` in (select id from `linkis_cg_manager_label` where `label_value` in (@KYUUBI_IDE, @KYUUBI_NODE));


delete from `linkis_ps_configuration_config_key` where `engine_conn_type` = 'kyuubi';

delete from `linkis_cg_manager_label` where `label_value` in (@KYUUBI_ALL, @KYUUBI_IDE, @KYUUBI_NODE);

最終的效果:

引擎引數

這樣配置完之後,linkis-cli 以及 Scripts 提交引擎指令碼時,才能正確匹配到引擎的標籤資訊和資料來源的連線資訊,然後才能拉起你新加的引擎。

2.10 DSS Scripts 中新增指令碼型別以及圖示等資訊

如果你使用到了 DSS 的 Scripts 功能,還需要對 dss 專案中 web 的前端檔案進行一些小小的改動,改動的目的是為了在 Scripts 中支援新建、開啟、執行新引擎指令碼型別,以及實現引擎對應的圖示、字型等。

2.10.1 scriptis.js

web/src/common/config/scriptis.js

{
rule: /\.kyuubi$/i,
// 語法高亮
lang: 'hql',
// 是否可執行
executable: true,
// application
application: 'kyuubi',
// 執行型別
runType: 'kyuubi',
// 指令碼副檔名
ext: '.kyuubi',
// 指令碼型別
scriptType: 'kyuubi',
abbr: 'kyuubi',
// 圖示
logo: 'fi-kyuubi',
// 配色
color: '#FF6666',
// 是否可被新建
isCanBeNew: true,
label: 'Kyuubi',
// 是否可被開啟
isCanBeOpen: true,
// 工作流型別
flowType: 'kyuubi'
},

2.10.2 指令碼複製支援

web/src/apps/scriptis/module/workSidebar/workSidebar.vue

copyName() {
let typeArr = ['......', 'kyuubi']
}

2.10.3 logo 與字型配色

web/src/apps/scriptis/module/workbench/title.vue

  data() {
return {
isHover: false,
iconColor: {
'fi-kyuubi': '#FF6666',
},
};
},

web/src/apps/scriptis/module/workbench/modal.js

let logoList = [
{ rule: /\.kyuubi$/i, logo: 'fi-kyuubi' },
];

web/src/components/tree/support.js

export const supportTypes = [
// 這裡大概沒用到
{ rule: /\.kyuubi$/i, logo: 'fi-kyuubi' },
]

引擎圖示展示

web/src/dss/module/resourceSimple/engine.vue

methods: {
calssifyName(params) {
switch (params) {
case 'kyuubi':
return 'Kyuubi';
......
}
}
// 圖示過濾
supportIcon(item) {
const supportTypes = [
......
{ rule: 'kyuubi', logo: 'fi-kyuubi' },
];
}
}

web/src/dss/assets/projectIconFont/iconfont.css

.fi-kyuubi:before {
content: "\e75e";
}

此處控制的應該是:

引擎圖示

找一個引擎圖示的 svg 檔案

web/src/components/svgIcon/svg/fi-kyuubi.svg

如果新引擎後續需要貢獻社群,那麼新引擎對應的 svg 圖示、字型等需要確認其所屬的開源協議,或獲取其版權許可。

2.11 DSS 的工作流適配

最終達成的效果:

工作流適配

在 dss_workflow_node 表中儲存新加 kyuubi 引擎的定義資料,參考 SQL:

# 引擎任務節點基本資訊定義
insert into `dss_workflow_node` (`id`, `name`, `appconn_name`, `node_type`, `jump_url`, `support_jump`, `submit_to_scheduler`, `enable_copy`, `should_creation_before_node`, `icon`) values('18','kyuubi','-1','linkis.kyuubi.kyuubi',NULL,'1','1','1','0','svg檔案');

# svg檔案對應新引擎任務節點圖示

# 引擎任務節點分類劃分
insert into `dss_workflow_node_to_group`(`node_id`,`group_id`) values (18, 2);

# 引擎任務節點的基本資訊(引數屬性)繫結
INSERT INTO `dss_workflow_node_to_ui`(`workflow_node_id`,`ui_id`) VALUES (18,45);

# 在dss_workflow_node_ui表中定義了引擎任務節點相關的基本資訊,然後以表單的形式在上圖右側中展示,你可以為新引擎擴充其他基礎資訊,然後自動被右側表單渲染。

web/src/apps/workflows/service/nodeType.js

import kyuubi from '../module/process/images/newIcon/kyuubi.svg';

const NODETYPE = {
......
KYUUBI: 'linkis.kyuubi.kyuubi',
}

const ext = {
......
[NODETYPE.KYUUBI]: 'kyuubi',
}

const NODEICON = {
[NODETYPE.KYUUBI]: {
icon: kyuubi,
class: {'kyuubi': true}
},
}

在 web/src/apps/workflows/module/process/images/newIcon/目錄下增加新引擎的圖示

web/src/apps/workflows/module/process/images/newIcon/kyuubi.svg

同樣貢獻社群時,請考慮 svg 檔案的 lincese 或版權。

3. 總結

上述內容記錄了新引擎的實現流程,以及額外需要做的一些引擎配置。本文主要基於 Apache Linkis 1.0.3,對 1.1.x 之後的版本也應適用。目前,一個新引擎的擴充套件流程還是比較繁瑣的,希望能在後續版本中,優化新引擎的擴充套件、以及安裝等過程。