diff --git a/README-ZH.md b/README-ZH.md index 216b6af862..bcfcfb709b 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -157,7 +157,7 @@ DSS主要特点: ## 快速安装使用 -点我进入[快速安装使用](docs/zh_CN/ch2/DSS快速安装使用文档.md) +点我进入[快速安装使用](docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md) ## 架构 @@ -167,7 +167,7 @@ DSS主要特点: #### 1. 安装编译文档 -[快速安装使用文档](docs/zh_CN/ch2/DSS快速安装使用文档.md) +[快速安装使用文档](docs/zh_CN/ch2/DSS_LINKIS_Quick_Install.md) [**DSS安装常见问题列表**](docs/zh_CN/ch1/DSS安装常见问题列表.md) @@ -203,4 +203,4 @@ DSS主要特点: ## License -DSS is under the Apache 2.0 license. See the [License](LICENSE) file for details. \ No newline at end of file +DSS is under the Apache 2.0 license. See the [License](LICENSE) file for details. diff --git a/conf/config.sh b/conf/config.sh index 5499f42c1d..dea8a60d7b 100644 --- a/conf/config.sh +++ b/conf/config.sh @@ -71,7 +71,7 @@ VISUALIS_NGINX_PORT=8088 #azkaban address for check AZKABAN_ADRESS_IP=127.0.0.1 -AZKABAN_ADRESS_PORT=8091 +AZKABAN_ADRESS_PORT=8081 #qualitis.address for check QUALITIS_ADRESS_IP=127.0.0.1 diff --git a/db/azkaban.sql b/db/azkaban.sql index 489ded7bb1..7f18b33087 100644 --- a/db/azkaban.sql +++ b/db/azkaban.sql @@ -1,3 +1,4 @@ INSERT INTO `dss_application` (`id`, `name`, `url`, `is_user_need_init`, `level`, `user_init_url`, `exists_project_service`, `project_url`, `enhance_json`, `if_iframe`, `homepage_url`, `redirect_url`) VALUES (NULL, 'schedulis', NULL, '0', '1', NULL, '0', NULL, NULL, '1', NULL, NULL); -UPDATE `dss_application` SET url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT', project_url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT/manager?project=${projectName}',homepage_url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT/homepage' WHERE `name` in - ('schedulis'); +UPDATE `dss_application` SET url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT', project_url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT/manager?project=${projectName}',homepage_url = 'http://AZKABAN_ADRESS_IP_2:AZKABAN_ADRESS_PORT/homepage' WHERE `name` in ('schedulis'); +SELECT @shcedulis_id:=id FROM `dss_application` WHERE `name` = 'schedulis'; +insert into dss_workflow_node values(null,null,'linkis.shell.sh',@shcedulis_id,1,1,0,1,null); diff --git "a/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" "b/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" index 0b9e779828..795de84515 100644 --- "a/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" +++ "b/docs/zh_CN/ch1/DSS\345\256\211\350\243\205\345\270\270\350\247\201\351\227\256\351\242\230\345\210\227\350\241\250.md" @@ -3,17 +3,20 @@ **本文档汇总DSS安装过程中所有问题列表及解决方式,为社区用户安装DSS提供参考。** -#### (1) 创建工程提示用户token为空 +#### (1) 创建工程失败:add scheduler project用户token为空 ``` -sudo vi dss-server/conf/token.properties -``` - -添加用户 +{"method":null,"status":1,"message":"error code(错误码): 90002, error message(错误信息): add scheduler project failederrCode: 90019 ,desc: errCode: 90020 ,desc: 用户token为空 ,ip: dss.com ,port: 9004 ,serviceKind: dss-server ,ip: dss.com ,port: 9004 ,serviceKind: dss-server.","data":{"errorMsg":{"serviceKind":"dss-server","level":2,"port":9004,"errCode":90002,"ip":"dss.com","desc":"add scheduler project failederrCode: 90019 ,desc: errCode: 90020 ,desc: 用户token为空 ,ip: dss.com ,port: 9004 ,serviceKind: dss-server ,ip: dss.com ,port: 9004 ,serviceKind: dss-server"}}} ``` -xxx=xxx -``` + +确保dss-server的token.properties中添加了此用户,并保持与 azkaban 的 azkaban-users.xml用户一致 +以hadoop用户为例: +1、在dss-server的token.properties添加 +hadoop=hadoop +2、在azkaban azkaban-users.xml 文件 添加 + start.log 2>start_error.log +``` + +     如果启动产生了错误信息,可以查看具体报错原因。启动后,各项微服务都会进行**通信检测**,如果有异常则可以帮助用户定位异常日志和原因。 + +     您可以通过查看我们的[启动常见问题](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch1/DSS%E5%AE%89%E8%A3%85%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%88%97%E8%A1%A8.md),获取问题的解答。 + +#### (2) 查看是否启动成功 + +     可以在Eureka界面查看 Linkis & DSS 后台各微服务的启动情况。如下图,如您的Eureka主页**启动日志会打印此访问地址**,出现以下微服务,则表示服务都启动成功,可以正常对外提供服务了: + + ![Eureka](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/images/zh_CN/chapter2/quickInstallUse/quickInstall.png) + +#### (3) 谷歌浏览器访问: + +请使用**谷歌浏览器**访问以下前端地址: + +`http://DSS_NGINX_IP:DSS_WEB_PORT` **启动日志会打印此访问地址**。登陆时管理员的用户名和密码均为部署用户名,如部署用户为hadoop,则管理员的用户名/密码为:hadoop/hadoop。 + +如果您想支持更多用户登录,详见 [Linkis LDAP](https://github.com/WeBankFinTech/Linkis/wiki/%E9%83%A8%E7%BD%B2%E5%92%8C%E7%BC%96%E8%AF%91%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93) + +如何快速使用DSS, 点我进入 [DSS快速使用文档](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch3/DSS_User_Manual.md) + +【DSS用户手册】提供了更加详尽的使用方法,点我进入 [DSS用户手册](https://github.com/WeBankFinTech/DataSphereStudio/blob/master/docs/zh_CN/ch3/DSS_User_Manual.md) +#### (4) 停止服务: +     在安装目录执行以下命令,停止所有服务:sh bin/stop-all.sh + +**注意** +1. 如果用户想启动和停止**单个应用**,可修改启动脚本注释掉其他应用的启动和停止命令即可。 + +2. 如果用户想启动和停止**单个微服务**,则可进入该微服务安装目录下执行sh bin/start-微服务名称.sh或sh bin/stop-微服务名称.sh + +## 五、云资源 +## 云资源 + +**我们提供了DSS + Linkis + Qualitis + Visualis + Azkaban【全家桶一键部署安装包】,由于安装包过大(1.3GB),Github下载缓慢,请通过以下方式获取**: + +**Baidu cloud:** + +- 百度云链接:https://pan.baidu.com/s/1hmxuJtyY72D5X_dZoQIE5g + +- Password: p82h + +**Tencent Cloud:** + +- 腾讯云链接:https://share.weiyun.com/5vpLr9t + +- Password: upqgib + +**DSS&Linkis 一键部署脚本** + +- URL:https://share.weiyun.com/5Qvl07X + +**以下为Linkis安装包资源:** + +- 腾讯云链接:https://share.weiyun.com/5Gjz0zU + +- 密码:9vctqg + +- 百度云链: +https://pan.baidu.com/s/1uuogWgLE9r8EcGROkRNeKg + +- 密码:pwbz + +**以下为DSS安装包资源:** + +- 腾讯云链接:https://share.weiyun.com/5n2GD0h + +- 密码:p8f4ug + +- 百度云链接:https://pan.baidu.com/s/18H8P75Y-cSEsW-doVRyAJQ + +- 密码:pnnj + +**附Qualitis及Azkaban单机版安装包资源:** + +- 腾讯云链接:https://share.weiyun.com/5fBPVIV + +- 密码:cwnhgw + +- 百度云链接:https://pan.baidu.com/s/1DYvm_KTljQpbdk6ZPx6K9g + +- 密码:3lnk diff --git "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" index 23c3008bc2..e775e8380e 100644 --- "a/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" +++ "b/docs/zh_CN/ch2/DSS\345\277\253\351\200\237\345\256\211\350\243\205\344\275\277\347\224\250\346\226\207\346\241\243.md" @@ -32,7 +32,7 @@ ## 二、精简版DSS环境配置准备 DSS环境配置准备分为三部分,前后端基础软件安装、后端环境配置准备和前端环配置境准备,详细介绍如下: ### 2.1 前后端基础软件安装 -Linkis简单版(0.9.3及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) +Linkis精简版(0.9.3及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) @@ -78,7 +78,7 @@ Nginx,[如何安装Nginx](https://www.tecmint.com/install-nginx-on-centos-7/) deployUser=hadoop #指定部署用户 - DSS_INSTALL_HOME=/appcom/Install/DSS #指定DSS的安装目录 + DSS_INSTALL_HOME=$workDir #默认为上一级目录 WORKSPACE_USER_ROOT_PATH=file:///tmp/Linkis #指定用户根目录,存储用户的脚本文件和日志文件等,是用户的工作空间。 @@ -189,7 +189,7 @@ Nginx,[如何安装Nginx](https://www.tecmint.com/install-nginx-on-centos-7/) deployUser=hadoop #指定部署用户 - DSS_INSTALL_HOME=/appcom/Install/DSS #指定DSS的安装目录 + DSS_INSTALL_HOME=$workDir #默认为上一级目录 WORKSPACE_USER_ROOT_PATH=file:///tmp/Linkis #指定用户根目录,存储用户的脚本文件和日志文件等,是用户的工作空间。 @@ -251,7 +251,7 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/ ## 四、标准版DSS环境配置准备 标准版DSS环境准备也分为三部分,前后端基础软件安装、后端环境准备和前端环境准备,详细介绍如下: ### 4.1 前后端基础软件安装 -Linkis简单版(0.9.3及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) +Linkis标准版(0.9.3及以上),[如何安装Linkis](https://github.com/WeBankFinTech/Linkis/wiki/%E5%A6%82%E4%BD%95%E5%BF%AB%E9%80%9F%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8Linkis) JDK (1.8.0_141以上),[如何安装JDK](https://www.runoob.com/java/java-environment-setup.html) @@ -302,7 +302,7 @@ Azkaban [如何安装Azkaban](https://github.com/azkaban/azkaban) deployUser=hadoop #指定部署用户 - DSS_INSTALL_HOME=/appcom/Install/DSS #指定DSS的安装目录 + DSS_INSTALL_HOME=$workDir #默认为上一级目录 WORKSPACE_USER_ROOT_PATH=file:///tmp/Linkis #指定用户根目录,存储用户的脚本文件和日志文件等,是用户的工作空间。 @@ -386,14 +386,12 @@ dss_ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/      安装模式就是简单模式或标准模式,请根据您准备的环境情况,选择合适的安装模式,精简版、简单模式和标准模式都会检查mysql服务,标准模式还会检测Qualitis服务和Azkaban外部server服务,如果检测失败会直接退出安装。 +- 安装过程如果有很多cp 命令提示您是否覆盖安装,说明您的系统配置有别名,输入alias,如果有cp、mv、rm的别名,如果有可以去掉,就不会再有大量提示。 + - install.sh脚本会询问您是否需要初始化数据库并导入元数据。      因为担心用户重复执行install.sh脚本,把数据库中的用户数据清空,所以在install.sh执行时,会询问用户是否需要初始化数据库并导入元数据。      **第一次安装**必须选是。 -- install.sh脚本会询问您是否需要初始化使用[davinci](https://github.com/edp963/davinci)所依赖的库表,如果您没有安装过davinci,则需要进行初始化建表,如果您已经安装了davinci,则无需再次初始化。 -     因为担心用户会mysql中已安装好的davinci数据清空,所以在install.sh执行时,会询问用户是否需要初始化。 -     **第一次安装**必须选是。 - ### c. 是否安装成功: diff --git a/docs/zh_CN/ch3/DSS_User_Manual.md b/docs/zh_CN/ch3/DSS_User_Manual.md index f366e5de31..5d91c0d02e 100644 --- a/docs/zh_CN/ch3/DSS_User_Manual.md +++ b/docs/zh_CN/ch3/DSS_User_Manual.md @@ -44,7 +44,17 @@ __注意:__ 如果要支持多用户登录,DSS的用户登录依赖Linkis, 3. 工程复制:以工程的最新版本为源工程,复制出新工程,初始版本工作流内容为源工程最新版本的工作流。注意:**工程名是唯一,不可重复** ## 3工作流——workflow -### 3.1 工作流编排 +### 3.1 工作流spark节点 +       spark节点分别支持sql、pyspark、scala三种方式执行spark任务,使用时只需将节点拖拽至工作台后编写代码即可。 +### 3.2 工作流hive节点 +       hive节点支持sql方式执行hive任务,使用时只需将节点拖拽至工作台后编写hivesql代码即可。 +### 3.3 工作流python节点 +       python节点支持执行python任务,使用时只需将节点拖拽至工作台后编写python代码即可。 +### 3.4 工作流shell节点 +       shell节点支持执行shell命令或者脚本运行,使用时只需将节点拖拽至工作台后编写shell命令即可。 +### 3.5 工作流jdbc节点 +       jdbc节点支持以jdbc方式运行sql命令,使用时只需将节点拖拽至工作台后编写sql即可,**注意需要提前在linkis console管理台配置jdbc连接信息。** +### 3.6 工作流编排        当点击一个对应的工程后,既可以进入工程首页,在工程首页可以做工作流的编排。 1. 首先需要创建工作流 ![workflow01](/images/zh_CN/chapter3/manual/workflow01.png) @@ -53,7 +63,7 @@ __注意:__ 如果要支持多用户登录,DSS的用户登录依赖Linkis, 3. 节点支持右键功能包括,删除、依赖选择、复制等基本功能,同时数据开发节点还支持脚本关联 ![workflow03](/images/zh_CN/chapter3/manual/workflow03.png) -### 3.2 工作流节点打开 +### 3.7 工作流节点打开 节点支持双击打开: 1. 数据开发节点:点开后即可进入Scriptis进行脚本编辑 ![workflow04](/images/zh_CN/chapter3/manual/workflow04.png) @@ -64,14 +74,14 @@ __注意:__ 如果要支持多用户登录,DSS的用户登录依赖Linkis, 4. 数据可视化节点:跳转到对应的可视化编辑页面 ![workflow07](/images/zh_CN/chapter3/manual/workflow07.png) -### 3.3 层级切换 +### 3.8 层级切换 1. 支持多层级切换:支持快速工程切换、支持在工作流页面切换工作流、支持在单个工作流中切换节点 ![workflow08](/images/zh_CN/chapter3/manual/workflow08.png) 2. 右上脚支持多组件快速切换,在切换后进入的组件的内容都只与该工程相关,让用户更加清晰的去定义工程和业务的内容: ![functions](/images/zh_CN/chapter3/manual/functions.png) -### 3.4 参数和资源设置 +### 3.9 参数和资源设置 1. 工作流上下文信息设置,支持工作流参数、变量、代理用户等 @@ -86,26 +96,26 @@ open("flow://test.txt", encoding="utf-8") #工作流级资源文件使用flow:/ open("node://test.txt", encoding="utf-8") #节点级资源文件使用node://开头 ``` -### 3.5 工作流实时执行 +### 3.10 工作流实时执行 1. 除了功能节点中的subflow会跳过执行,连接节点会作为空节点运行,其他都支持实时执行 ![workflow11](/images/zh_CN/chapter3/manual/workflow11.png) 2. 用户编辑好工作流后点击执行就可以将工作流进行运行,您将看到实时的工作流运行起来可以看到现在运行节点的时间,同时可以右键节点打开节点的管理台去展示该节点的进度,运行结果,运行日志等。支持任务停止等功能 ![workflow12](/images/zh_CN/chapter3/manual/workflow12.png) -### 3.6 工作流调度执行 +### 3.11 工作流调度执行 1. DSS的工程支持发布调度,默认支持发布到Azkaban,同样DSS的调度部分做了深层次的抽象可以做到对其他的调度系统快速支持。发布前会对工作流进行解析,以确保工作流是可以调度运行的: ![workflow13](/images/zh_CN/chapter3/manual/workflow13.png) 2. 发布后即可到调度系统中进行查看,比如去Azkaban页面上进行查看: ![workflow14](/images/zh_CN/chapter3/manual/workflow14.png) 3. DSS如何对接调度系统可以参考:[]() -### 3.7 工作流版本 +### 3.12 工作流版本 1. 工作流创建完成后,具有初始版本,版本号为v000001,直接点击工作流图标时,默认打开工作流的最新版本 2. 可以查看工作流的版本,方便您进行历史版本查看: ![workflow15](/images/zh_CN/chapter3/manual/workflow15.png) -### 3.8 工作流布局修改 +### 3.13 工作流布局修改 1. 工作流格式化:当工作流节点过多,界面太乱时。可以点击节点编辑页的右上方第四个“格式化”按钮。快速美化节点界面: ![workflow16](/images/zh_CN/chapter3/manual/workflow16.png) 如果格式化后不满意,可再次点击节点编辑页的右上方第五个“恢复”按钮,恢复到之前的状态: diff --git "a/docs/zh_CN/ch4/\347\254\254\344\270\211\346\226\271\347\263\273\347\273\237\346\216\245\345\205\245DSS\346\214\207\345\215\227.md" "b/docs/zh_CN/ch4/\347\254\254\344\270\211\346\226\271\347\263\273\347\273\237\346\216\245\345\205\245DSS\346\214\207\345\215\227.md" index 73173626eb..690682aabe 100644 --- "a/docs/zh_CN/ch4/\347\254\254\344\270\211\346\226\271\347\263\273\347\273\237\346\216\245\345\205\245DSS\346\214\207\345\215\227.md" +++ "b/docs/zh_CN/ch4/\347\254\254\344\270\211\346\226\271\347\263\273\347\273\237\346\216\245\345\205\245DSS\346\214\207\345\215\227.md" @@ -31,28 +31,142 @@         NodeService是用来解决用户在DSS提交的任务在第三方系统生成相应的任务的问题。用户如果在DSS系统的工作流中新建了一个工作流节点并进行任务的编辑,第三方系统需要同步感知到 - 4.getNodeExecution -        NodeExecution接口是用来将任务提交到第三方系统进行执行的接口,NodeExecution接口有支持短时间任务的NodeExecution和支持长时间任务的LongTermNodeExecution。一般短时间任务,如邮件发送等,可以直接实现NodeExecution接口,并重写execute方法,DSS系统同步等待任务结束。另外的长时间任务,如数据质量检测等,可以实现LongTermNodeExecution接口,并重写submit方法,返回一个NodeExecutionAction,DSS系统通过这个NodeExecutionAction可以向第三方系统获取任务的日志、状态等。 +        NodeExecution接口是用来将任务提交到第三方系统进行执行的接口,NodeExecution +接口有支持短时间任务的NodeExecution和支持长时间任务的LongTermNodeExecution。一般短时间任务,如邮件发送等,可以直接实现NodeExecution接口,并重写execute方法,DSS系统同步等待任务结束。另外的长时间任务,如数据质量检测等,可以实现LongTermNodeExecution接口,并重写submit方法,返回一个NodeExecutionAction,DSS系统通过这个NodeExecutionAction可以向第三方系统获取任务的日志、状态等。 #### 3.第三方系统接入DSS的实现(以Visualis为例) -        Visualis是微众银行WeDataSphere开源的一款商业BI工具,DSS集成Visualis系统之后可以获得数据可视化的能力。Visualis接入DSS系统的代码在DSS项目中已经同步开源,下面将以开源代码为例,对步骤进行罗列分析。 +        Visualis是微众银行WeDataSphere开源的一款商业BI工具,DSS集成Visualis系统之后可以获得数据可视化的能力。 +Visualis接入DSS系统的代码在DSS项目中已经同步开源,下面将以开源代码为例,对步骤进行罗列分析。 Visualis接入的DSS系统的步骤如下: **3.1.Visualis实现AppJoint接口** -        Visualis实现的 AppJoint接口的实现类是VisualisAppjoint。查看VisualisAppjoint的代码可知,它在init方法时候,初始化了自己实现的SecurityService、 NodeService以及NodeExecution。 +        Visualis实现的 AppJoint接口的实现类是VisualisAppjoint。查看VisualisAppjoint的代码可知,它在init方法时候, +初始化了自己实现的SecurityService、 NodeService以及NodeExecution。 +```java + public void init(String baseUrl, Map params) { + securityService = new VisualisSecurityService(); + securityService.setBaseUrl(baseUrl); + nodeExecution = new VisualisNodeExecution(); + nodeExecution.setBaseUrl(baseUrl); + nodeService = new VisualisNodeService(); + nodeService.setBaseUrl(baseUrl); + } +``` **3.2.Visualis实现SecurtyService接口** -        Visualis实现的SecurityService接口的类名是VisualisSecurityService,并重写了login方法,为了能够进行授权登陆,Visualis采用了提供token的方式,DSS的网关对该token进行授权,这样就能够做到用户鉴权。 +        Visualis实现的SecurityService接口的类名是VisualisSecurityService, +并重写了login方法,为了能够进行授权登陆,Visualis采用了提供token的方式,DSS的网关对该token进行授权,这样就能够做到用户鉴权。 + +```java +public class VisualisSecurityService extends AppJointUrlImpl implements SecurityService { + @Override + public Session login(String user) throws AppJointErrorException { + VisualisSession visualisSession = new VisualisSession(); + visualisSession.setUser(user); + visualisSession.getParameters().put("Token-User",user); + visualisSession.getParameters().put("Token-Code","WS-AUTH"); + return visualisSession; + } + + @Override + public void logout(String user) { + + } +} +``` **3.3.Visualis实现的NodeService接口** -        Visualis实现的NodeService接口的类是VisualisNodeService,并重写了createNode,deleteNode和updateNode三个方法,这三个方法是进行在第三方系统同步生成任务元数据。例如createNode方法是通过调用visualis的HTTP接口在Visualis系统生成同一工程下面的Visualis任务。 +        Visualis实现的NodeService接口的类是VisualisNodeService,并重写了createNode, +deleteNode和updateNode三个方法,这三个方法是进行在第三方系统同步生成任务元数据。例如createNode方法是通过调用visualis的HTTP接口在Visualis系统生成同一工程下面的Visualis任务。 + +```java + @Override + public Map createNode(Session session, AppJointNode node, + Map requestBody) throws AppJointErrorException { + if (DisplayNodeService.getNodeType().equals(node.getNodeType())) { + return DisplayNodeService.createNode(session, getBaseUrl(), String.valueOf(node.getProjectId()), node.getNodeType(), requestBody); + } else if (DashboardNodeService.getNodeType().equals(node.getNodeType())) { + return DashboardNodeService.createNode(session, getBaseUrl(), String.valueOf(node.getProjectId()), node.getNodeType(), requestBody); + } else { + throw new AppJointErrorException(42002, "cannot recognize the nodeType " + node.getNodeType()); + } + } + + @Override + public void deleteNode(Session session, AppJointNode node) throws AppJointErrorException { + if (DisplayNodeService.getNodeType().equals(node.getNodeType())) { + DisplayNodeService.deleteNode(session, getBaseUrl(), String.valueOf(node.getProjectId()), node.getNodeType(), node.getJobContent()); + } else if (DashboardNodeService.getNodeType().equals(node.getNodeType())) { + DashboardNodeService.deleteNode(session, getBaseUrl(), String.valueOf(node.getProjectId()), node.getNodeType(), node.getJobContent()); + } else { + throw new AppJointErrorException(42002, "cannot recognize the nodeType " + node.getNodeType()); + } + } + + @Override + public Map updateNode(Session session, AppJointNode node, + Map requestBody) throws AppJointErrorException { + if (DisplayNodeService.getNodeType().equals(node.getNodeType())) { + return DisplayNodeService.updateNode(session, getBaseUrl(), node.getProjectId(), node.getNodeType(), requestBody); + } else if (DashboardNodeService.getNodeType().equals(node.getNodeType())) { + return DashboardNodeService.updateNode(session, getBaseUrl(), node.getProjectId(), node.getNodeType(), requestBody); + } else { + throw new AppJointErrorException(42002, "cannot recognize the nodeType " + node.getNodeType()); + } + } +``` **3.4.Visualis实现NodeExecution接口** -        Visualis实现的NodeExecution接口的类是VisualisNodeExecution,并重写了execute方法,该方法传入的两个参数为Node和NodeContext,从NodeContext中我们可以拿到用户、DSS的网关地址,还有网关验证的Token。通过这些,我们可以封装成一个HTTP的请求发送到第三方系统Visualis并从Visualis获取响应结果,NodeContext提供写入结果集的方法,如Visualis的结果集一般是以图片的形式展示,在execute方法的最后,Visualis通过nodeContext获取到一个支持图片写入的PictureResultSetWriter方法,并将结果集进行写入。 +        Visualis实现的NodeExecution接口的类是VisualisNodeExecution,并重写了execute方法, +该方法传入的两个参数为Node和NodeContext,从NodeContext中我们可以拿到用户、DSS的网关地址,还有网关验证的Token。 +通过这些,我们可以封装成一个HTTP的请求发送到第三方系统Visualis并从Visualis获取响应结果,NodeContext提供写入结果集的方法, +如Visualis的结果集一般是以图片的形式展示,在execute方法的最后,Visualis通过nodeContext获取到一个支持图片写入的PictureResultSetWriter方法,并将结果集进行写入。 +```scala + override def execute(node: AppJointNode, nodeContext: NodeContext, session: Session): NodeExecutionResponse = node match { + case commonAppJointNode: CommonAppJointNode => + val appJointResponse = new CompletedNodeExecutionResponse() + val idMap = commonAppJointNode.getJobContent + val id = idMap.values().iterator().next().toString + val url = if(commonAppJointNode.getNodeType.toLowerCase.contains(DISPLAY)) getDisplayPreviewUrl(nodeContext.getGatewayUrl, id) + else if(commonAppJointNode.getNodeType.toLowerCase.contains(DASHBOARD)) getDashboardPreviewUrl(nodeContext.getGatewayUrl, id) + else { + appJointResponse.setIsSucceed(false) + appJointResponse.setErrorMsg("不支持的appJoint类型:" + node.getNodeType) + return appJointResponse + } + var response = "" + val headers = nodeContext.getTokenHeader(nodeContext.getUser) + nodeContext.appendLog(LogUtils.generateInfo(s"Ready to download preview picture from $url.")) + Utils.tryCatch(download(url, null, headers.toMap, + input => Utils.tryFinally{ + val os = new ByteArrayOutputStream() + IOUtils.copy(input, os) + response = new String(Base64.getEncoder.encode(os.toByteArray)) + //response = IOUtils.toString(input, ServerConfiguration.BDP_SERVER_ENCODING.getValue) + }(IOUtils.closeQuietly(input)))){ t => + val errException = new ErrorException(70063, "failed to do visualis request") + errException.initCause(t) + appJointResponse.setException(errException) + appJointResponse.setIsSucceed(false) + appJointResponse.setErrorMsg(s"用户${nodeContext.getUser}请求Visualis失败!URL为: " + url) + return appJointResponse + } + nodeContext.appendLog(LogUtils.generateInfo("Preview picture downloaded, now ready to write results.")) + val imagesBytes = response + val resultSetWriter = nodeContext.createPictureResultSetWriter() + Utils.tryFinally{ + resultSetWriter.addMetaData(new LineMetaData()) + resultSetWriter.addRecord(new LineRecord(imagesBytes)) + }(IOUtils.closeQuietly(resultSetWriter)) + appJointResponse.setIsSucceed(true) + appJointResponse + } +``` **3.5.数据库内容的更新(dss-application模块)** @@ -66,7 +180,7 @@ Visualis接入的DSS系统的步骤如下: | url | 10 | 如 http://127.0.0.1:8080 | | is_user_need_init | 是否需要用户初始化 | 默认否 | | user_init_url | 用户初始化url | 默认空 | -| exists_project_service | 是否存在自己的projectService服务, 存在的话要自己写appjoint实现projectService0 | | +| exists_project_service | 是否存在自己的projectService服务, 存在的话要自己写appjoint实现projectService | | | enhance_json | 加强json,在appjoint初始化的时候会作为map进行传入 | | | homepage_url | 接入的系统主页url | | | direct_url | 接入的系统重定向url | | @@ -97,11 +211,11 @@ Visualis接入的DSS系统的步骤如下: **3.6.前端的修改** - 3.6.1 增加节点类型 -修改src/js/service/nodeType.js文件,增加Qualitis节点类型 +修改src/js/service/nodeType.js文件,增加Visualis节点类型 - 3.6.2 增加节点图标 将节点图标复制到src/js/module/process/images/路径下,目前只支持SVG格式。 - 3.6.3 新增节点配置 -修改src/js/module/process/shape.js文件,增加Qualitis的节点配置信息。 +修改src/js/module/process/shape.js文件,增加Visualis的节点配置信息。 - 3.6.4 修改首页单击节点事件 修改src/js/module/process/index.vue文件,增加节点单击事件以及单击事件的处理逻辑。 - 3.6.5 修改工作流节点双击事件 @@ -109,7 +223,13 @@ Visualis接入的DSS系统的步骤如下: **3.7.编译打包成jar包放置到指定位置** -        实现了上述的接口之后,一个AppJoint就已经实现了。打包之后,需要放置到指定的位置。jar包需要放置到dss-server和linkis-appjoint-entrance两个微服务中,以linkis-appjoint-entrance 为例(dss-server与linkis-appjoint-entrance一致),在linkis-appjont-entrance下面的lib的同级目录有一个appjoints目录,目录下面层次如图3-3所示。 +        实现了上述的接口之后,一个AppJoint就已经实现了。打包之后,需要放置到指定的位置。 +jar包需要放置到dss-server和linkis-appjoint-entrance两个微服务中,以linkis-appjoint-entrance 为例(dss-server与linkis-appjoint-entrance一致), +在linkis-appjont-entrance下面的lib的同级目录有一个appjoints目录,目录下面层次如图3-3所示。 ![appjoints目录示例](/images/zh_CN/chapter4/appjoints.png)
图3-3 appjoints目录示例 -        在appjoints目录下面新建一个visualis目录。visualis目录下面要求有lib目录,lib目录存放的是visualis在实现VisualisAppJoint的编译的jar包,当然如果有引入dss系统没有带入的jar包,也需要放置到lib目录中,如sendemail Appjoint需要发送邮件功能的依赖包,所以需要将这些依赖包和已经实现的jar包统一放置到lib目录中。另外可以将本AppJoint所需要的一些配置参数放置到appjoints.properties,DSS系统提供的AppJointLoader会将这些配置的参数读取,放置到一个Map中,在AppJoint调用init方法的时候传入。 +        在appjoints目录下面新建一个visualis目录。 +visualis目录下面要求有lib目录,lib目录存放的是visualis在实现VisualisAppJoint的编译的jar包, +当然如果有引入dss系统没有带入的jar包,也需要放置到lib目录中,如sendemail Appjoint需要发送邮件功能的依赖包, +所以需要将这些依赖包和已经实现的jar包统一放置到lib目录中。 +另外可以将本AppJoint所需要的一些配置参数放置到appjoints.properties,DSS系统提供的AppJointLoader会将这些配置的参数读取,放置到一个Map中,在AppJoint调用init方法的时候传入。 diff --git a/web/package.json b/web/package.json index 09814a5fba..95693d3273 100644 --- a/web/package.json +++ b/web/package.json @@ -35,7 +35,7 @@ "md5": "^2.2.1", "mitt": "^1.1.3", "moment": "^2.22.2", - "monaco-editor": "^0.15.1", + "monaco-editor": "^0.20.0", "pinyin": "^2.9.0", "qs": "^6.9.1", "reconnecting-websocket": "^4.1.10", diff --git a/web/src/js/component/editor/editor.vue b/web/src/js/component/editor/editor.vue index 1418ae01aa..dad5484c92 100644 --- a/web/src/js/component/editor/editor.vue +++ b/web/src/js/component/editor/editor.vue @@ -91,7 +91,7 @@ export default { if (newValue == this.getValue()) { return; } - let readOnly = this.editor.getConfiguration().readOnly; + let readOnly = this.editor.getRawOptions().readOnly; if (readOnly) { // editor.setValue 和 model.setValue 都会丢失撤销栈 this.editor.setValue(newValue); diff --git a/web/src/js/module/process/component/associateScript.vue b/web/src/js/module/process/component/associateScript.vue index 26b4ea9697..545c633390 100644 --- a/web/src/js/module/process/component/associateScript.vue +++ b/web/src/js/module/process/component/associateScript.vue @@ -38,7 +38,7 @@ import { isEmpty, cloneDeep } from 'lodash'; import storage from '@/js/helper/storage'; import directoryDialog from '@js/component/directoryDialog/index.vue'; - +import { ext } from '@/js/service/nodeType'; export default { components: { directoryDialog, @@ -82,8 +82,8 @@ export default { this.setFileTree(); }); this.filterNode = (node) => { - const type = this.nodeData.type.slice(this.nodeData.type.lastIndexOf('.') + 1, this.nodeData.type.length); - const match = this.supportModes.find((item) => item.rule.test(node.label) && item.flowType === type); + const model = ext[this.nodeData.type]; + const match = this.supportModes.find((item) => item.rule.test(node.label) && item.flowType === model); return !node.isLeaf || (node.isLeaf && match); }; }, diff --git a/web/src/js/service/mixin.js b/web/src/js/service/mixin.js index 90341c5ddd..4ca8713dc7 100644 --- a/web/src/js/service/mixin.js +++ b/web/src/js/service/mixin.js @@ -34,7 +34,7 @@ export default { { rule: /\.python$/i, lang: 'python', executable: true, application: 'python', runType: 'python', ext: '.python', scriptType: 'python', abbr: 'py', logo: 'fi-python', isCanBeNew: true, label: 'Python', isCanBeOpen: true, flowType: 'python' }, { rule: /\.py$/i, lang: 'python', executable: true, application: 'spark', runType: 'python', ext: '.py', scriptType: 'pythonSpark', abbr: 'py', logo: 'fi-spark-python', isCanBeNew: true, label: 'PythonSpark', isCanBeOpen: true, flowType: 'pyspark' }, { rule: /\.r$/i, lang: 'r', executable: true, application: 'spark', runType: 'r', ext: '.r', scriptType: 'r', abbr: 'r', logo: 'fi-r', isCanBeNew: true, label: 'R', isCanBeOpen: true }, - { rule: /\.sh$/i, lang: 'sh', executable: true, application: 'shell', runType: 'shell', ext: '.sh', scriptType: 'shell', abbr: 'shell', logo: 'fi-r', isCanBeNew: false, label: 'Shell', isCanBeOpen: true, flowType: 'shell' }, + { rule: /\.sh$/i, lang: 'sh', executable: true, application: 'shell', runType: 'shell', ext: '.sh', scriptType: 'shell', abbr: 'shell', logo: 'fi-r', isCanBeNew: true, label: 'Shell', isCanBeOpen: true, flowType: 'shell' }, { rule: /\.qmlsql$/i, lang: 'hql', executable: false, application: 'spark', runType: 'sql', ext: '.qmlsql', scriptType: 'qmlsql', abbr: 'qmlsql', logo: 'fi-spark', isCanBeNew: false, label: 'QMLSQL', isCanBeOpen: true }, { rule: /\.qmlpy$/i, lang: 'python', executable: false, application: 'spark', runType: 'python', ext: '.qmlpy', scriptType: 'qmlpy', abbr: 'qmlpy', logo: 'fi-python', isCanBeNew: false, label: 'QMLPy', isCanBeOpen: true }, { rule: /\.txt$/i, lang: 'text', executable: false, application: null, runType: null, ext: '.txt', scriptType: 'txt', abbr: '', logo: 'fi-txt', isCanBeNew: false, isCanBeOpen: true }, diff --git a/web/src/js/service/nodeType.js b/web/src/js/service/nodeType.js index bf0a654985..5b6a55803b 100644 --- a/web/src/js/service/nodeType.js +++ b/web/src/js/service/nodeType.js @@ -34,7 +34,7 @@ import qualitis from '../module/process/images/newIcon/qualitis.svg'; import python from '../module/process/images/newIcon/python.svg'; import jdbc from '../module/process/images/newIcon/JDBC2.svg'; const NODETYPE = { - SHELL: 'azkaban.shell', + SHELL: 'linkis.shell.sh', HQL: 'linkis.hive.hql', SPARKSQL: 'linkis.spark.sql', SPARKPY: 'linkis.spark.py',