因为在工作中需要推动Apache DolphinScheduler的升级,经过预研,从1.3.4到3.1.2有的体验了很大的提升,在性能和功能性有了很多的改善,推荐升级。

查看官方的升级文档,可知有提供升级脚本,如果只是跨小版本的更新那么只用执行脚本就好了,但跨多个大版本升级时依然容易出现各种问题,特此总结

旧版本:1.3.4
新版本:3.1.2

问题合集

1.资源中心报错

升级完成后使用资源中心报错 IllegalArgumentException: Failed to specify server's Kerberos principal name

资源中心使用的HDFS,开启了kerberos认证

解决方法:

编辑 dolphinscheduler/api-server/conf/hdfs-site.xml 添加以下内容

<property>
<name>dfs.namenode.kerberos.principal.pattern</name>
<value>*</value>
</property>

2.任务实例日志丢失

升级完成后查看任务实例的日志,报错未找到日志,查看报错信息,检查新版本的目录结构和表里的日志路径,发现原因是新版本的日志路径有变更。

升级前的日志路径在 /logs/ 下。

升级后的日志路径在 /worker-server/logs/ 下。

因此需要修改这里的目录

解决方法:

执行SQL修改日志路径

update t_ds_task_instance set log_path=replace(log_path,'/logs/','/worker-server/logs/');

然后将原日志文件copy到新的日志路径

cp -r {旧版本dolphinscheduler目录}/logs/[1-9]* {新版本dolphinscheduler目录}/worker-server/logs/*

3.升级完创建工作流报错

查看报错信息,原因是 t_ds_process_definition_logt_ds_process_definition 主键的初始值不一致,那么修改成一致的就好了!

解决方法:

执行SQL

# 查出主键自增值
select AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'dolphinscheduler' AND TABLE_NAME = 't_ds_process_definition' limit 1
# 将上面SQL的执行结果填写到下方参数处执行
alter table dolphinscheduler_bak1.t_ds_process_definition_log auto_increment = {max_id};

4.升级后任务实例列表为空

检查查询的SQL

dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/TaskInstanceMapper.xml 文件里,select id="queryTaskInstanceListPaging"的SQL

       	select
<include refid="baseSqlV2">
<property name="alias" value="instance"/>
</include>
,
process.name as process_instance_name
from t_ds_task_instance instance
left join t_ds_task_definition_log define on define.code=instance.task_code and define.version=instance.task_definition_version
left join t_ds_process_instance process on process.id=instance.process_instance_id
where define.project_code = #{projectCode}
<if test="startTime != null">
and instance.start_time <![CDATA[ >=]]> #{startTime}
</if>
......省略多余部分

查询任务实例列表的SQL会关联 t_ds_task_definition_log 表,经检查发现是 define.code=instance.task_code 这一句关联不上。

结合下面的查询条件 define.project_code = #{projectCode} 可知,关联 t_ds_task_definition_log 主要是为了过滤 projectCode,那么来修改下这个SQL:

解决方法:

    	select
<include refid="baseSqlV2">
<property name="alias" value="instance"/>
</include>
,
process.name as process_instance_name
from t_ds_task_instance instance
-- left join t_ds_task_definition_log define
-- on define.code=instance.task_code and
-- define.version=instance.task_definition_version
join t_ds_process_instance process
on process.id=instance.process_instance_id
join t_ds_process_definition define
on define.code=process.process_definition_code
where define.project_code = #{projectCode}
<if test="startTime != null">
and instance.start_time <![CDATA[ >=]]> #{startTime}
</if>
......省略多余部分

直接用 t_ds_process_definition 关联,也有 project_code 字段可以用来关联过滤,这里修改后就能查出数据了。

5.执行升级脚本的过程中报空指针

(1)分析日志,定位到 UpgradeDao.java 517行

查看代码

513 if (TASK_TYPE_SUB_PROCESS.equals(taskType)) {
514 JsonNode jsonNodeDefinitionId = param.get("processDefinitionId");
515 if (jsonNodeDefinitionId != null) {
516 param.put("processDefinitionCode",
517 processDefinitionMap.get(jsonNodeDefinitionId.asInt()).getCode());
518 param.remove("processDefinitionId");
519 }
520 }

很明显是 processDefinitionMap.get(jsonNodeDefinitionId.asInt()) 返回了null,加个null判断,如果返回null直接跳过,并将相关信息打印出来,升级结束后可以根据日志核对。

解决方法:

修改后:

if (jsonNodeDefinitionId != null) {
if (processDefinitionMap.get(jsonNodeDefinitionId.asInt()) != null) {
param.put("processDefinitionCode",processDefinitionMap.get(jsonNodeDefinitionId.asInt()).getCode());
param.remove("processDefinitionId");
} else {
logger.error("*******************error");
logger.error("*******************param:" + param);
logger.error("*******************jsonNodeDefinitionId:" + jsonNodeDefinitionId);
}
}
(2)分析日志,定位到 UpgradeDao.java 675行

查看代码

669 if (mapEntry.isPresent()) {
670 Map.Entry<Long, Map<String, Long>> processCodeTaskNameCodeEntry = mapEntry.get();
671 dependItem.put("definitionCode", processCodeTaskNameCodeEntry.getKey());
672 String depTasks = dependItem.get("depTasks").asText();
673 long taskCode =
674 "ALL".equals(depTasks) || processCodeTaskNameCodeEntry.getValue() == null ? 0L
675 : processCodeTaskNameCodeEntry.getValue().get(depTasks);
676 dependItem.put("depTaskCode", taskCode);
677 }

很明显是 processCodeTaskNameCodeEntry.getValue().get(depTasks) 返回了null,修改下逻辑,不为null才赋值并打印相关日志。

解决方法:

修改后:

long taskCode =0;
if (processCodeTaskNameCodeEntry.getValue() != null
&&processCodeTaskNameCodeEntry.getValue().get(depTasks)!=null){
taskCode =processCodeTaskNameCodeEntry.getValue().get(depTasks);
}else{
logger.error("******************** depTasks:"+depTasks);
logger.error("******************** taskCode not in "+JSONUtils.toJsonString(processCodeTaskNameCodeEntry));
}
dependItem.put("depTaskCode", taskCode);

6.接入LDAP后登陆失败,不知道Email字段名

可在 api-server/conf/application.yaml 配置接入LDAP

security:
authentication:
# Authentication types (supported types: PASSWORD,LDAP)
type: LDAP
# IF you set type `LDAP`, below config will be effective
ldap:
# ldap server config
urls: xxx
base-dn: xxx
username: xxx
password: xxx
user:
# admin userId when you use LDAP login
admin: xxx
identity-attribute: xxx
email-attribute: xxx
# action when ldap user is not exist (supported types: CREATE,DENY)
not-exist-action: CREATE

要成功接入LDAP至少需要urls,base-dn,username,password,identity和email正确填写,不知道email字段名可以按下面的方式处理,email先空着

启动服务后用LDAP用户登录

解决办法:

LDAP 认证的代码在 dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapService.javaldapLogin()

ctx = new InitialLdapContext(searchEnv, null);
SearchControls sc = new SearchControls();
sc.setReturningAttributes(new String[]{ldapEmailAttribute});
sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
EqualsFilter filter = new EqualsFilter(ldapUserIdentifyingAttribute, userId);
NamingEnumeration<SearchResult> results = ctx.search(ldapBaseDn, filter.toString(), sc);
if (results.hasMore()) {
// get the users DN (distinguishedName) from the result
SearchResult result = results.next();
NamingEnumeration<? extends Attribute> attrs = result.getAttributes().getAll();
while (attrs.hasMore()) {
// Open another connection to the LDAP server with the found DN and the password
searchEnv.put(Context.SECURITY_PRINCIPAL, result.getNameInNamespace());
searchEnv.put(Context.SECURITY_CREDENTIALS, userPwd);
try {
new InitialDirContext(searchEnv);
} catch (Exception e) {
logger.warn("invalid ldap credentials or ldap search error", e);
return null;
}
Attribute attr = attrs.next();
if (attr.getID().equals(ldapEmailAttribute)) {
return (String) attr.get();
}
}
}

第三行会根据填的字段过滤,先注释第三行

// sc.setReturningAttributes(new String[]{ldapEmailAttribute});

重新执行后第10行会返回全部字段

NamingEnumeration<? extends Attribute> attrs = result.getAttributes().getAll();

通过打印或调试在里面找到email字段填到配置文件里,再还原上面注释的代码,重启服务后即可正常接入LDAP登录。

7.管理员给普通用户授权资源文件不生效

经多次测试,发现普通用户只能看到所属用户为自己的资源文件,管理员授权后依然无法查看资源文件

解决办法:

文件 dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/permission/ResourcePermissionCheckServiceImpl.javalistAuthorizedResource() 方法,将 return 的集合修改为 relationResources

@Override
public Set<Integer> listAuthorizedResource(int userId, Logger logger) {
List<Resource> relationResources;
if (userId == 0) {
relationResources = new ArrayList<>();
} else {
// query resource relation
List<Integer> resIds = resourceUserMapper.queryResourcesIdListByUserIdAndPerm(userId, 0);
relationResources = CollectionUtils.isEmpty(resIds) ? new ArrayList<>() : resourceMapper.queryResourceListById(resIds);
}
List<Resource> ownResourceList = resourceMapper.queryResourceListAuthored(userId, -1);
relationResources.addAll(ownResourceList);
return relationResources.stream().map(Resource::getId).collect(toSet()); // 解决资源文件授权无效的问题
// return ownResourceList.stream().map(Resource::getId).collect(toSet());
}

检查新版本的 Change log ,发现在3.1.3版本修复了这个bug

https://github.com/apache/dolphinscheduler/pull/13318

8.kerberos过期的问题

因为kerberos配置了票据过期时间,一段时间后资源中心的hdfs资源将无法访问,最好的解决办法是添加定时更新凭证的相关逻辑。

解决办法:

在文件 dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/utils/CommonUtils.java 添加方法

 /**
* * 定时更新凭证
*/
private static void startCheckKeytabTgtAndReloginJob() {
// 每天循环,定时更新凭证
Executors.newScheduledThreadPool(1).scheduleWithFixedDelay(() -> {
try {
UserGroupInformation.getLoginUser().checkTGTAndReloginFromKeytab();
logger.warn("Check Kerberos Tgt And Relogin From Keytab Finish.");
} catch (IOException e) {
logger.error("Check Kerberos Tgt And Relogin From Keytab Error", e);
}
}, 0, 1, TimeUnit.DAYS);
logger.info("Start Check Keytab TGT And Relogin Job Success.");
}

然后在该文件的 loadKerberosConf 方法返回 true 前调用:

public static boolean loadKerberosConf(String javaSecurityKrb5Conf, String loginUserKeytabUsername,
String loginUserKeytabPath, Configuration configuration) throws IOException {
if (CommonUtils.getKerberosStartupState()) {
System.setProperty(Constants.JAVA_SECURITY_KRB5_CONF, StringUtils.defaultIfBlank(javaSecurityKrb5Conf,
PropertyUtils.getString(Constants.JAVA_SECURITY_KRB5_CONF_PATH)));
configuration.set(Constants.HADOOP_SECURITY_AUTHENTICATION, Constants.KERBEROS);
UserGroupInformation.setConfiguration(configuration);
UserGroupInformation.loginUserFromKeytab(
StringUtils.defaultIfBlank(loginUserKeytabUsername,
PropertyUtils.getString(Constants.LOGIN_USER_KEY_TAB_USERNAME)),
StringUtils.defaultIfBlank(loginUserKeytabPath,
PropertyUtils.getString(Constants.LOGIN_USER_KEY_TAB_PATH)));
startCheckKeytabTgtAndReloginJob(); // 此处调用
return true;
}
return false;
}

这篇文章主要是记录升级过程中遇到的问题,希望能够对大家有所帮助!

本文由 白鲸开源 提供发布支持!

Apache DolphinScheduler 1.3.4升级至3.1.2版本过程中的踩坑记录的更多相关文章

  1. Windows+Apache+Python+Django 踩坑记录

    摘要 使用Python进行Web项目开发:相对于主流三大Web端解决方案(Java/.NET/PHP) Python在某些方面具有一定的优势,相对 Java/.NET 有更轻量级的部署方案,相对PHP ...

  2. 论语音社交视频直播平台与 Apache DolphinScheduler 的适配度有多高

    在 Apache DolphinScheduler& Apache ShenYu(Incubating) Meetup 上,YY 直播 软件工程师 袁丙泽 为我们分享了<YY直播基于Ap ...

  3. 日均 6000+ 实例,TB 级数据流量,Apache DolphinScheduler 如何做联通医疗大数据平台的“顶梁柱”?

    作者 | 胡泽康 鄞乐炜 作者简介 胡泽康 联通(广东)产业互联网公司  大数据工程师,专注于开源大数据领域,从事大数据平台研发工作 鄞乐炜 联通(广东)产业互联网公司 大数据工程师,主要从事大数据平 ...

  4. Apache DolphinScheduler 2.0.1 来了,备受期待的一键升级、插件化终于实现

    ✎ 编 者 按:好消息!Apache DolphinScheduler 2.0.1 版本正式发布! 本版本中,DolphinScheduler 经历了一场微内核+插件化的架构改进,70% 的代码被重构 ...

  5. 从 Airflow 到 Apache DolphinScheduler,有赞大数据开发平台的调度系统演进

    点击上方 蓝字关注我们 作者 | 宋哲琦 ✎ 编 者 按 在不久前的 Apache  DolphinScheduler Meetup 2021 上,有赞大数据开发平台负责人 宋哲琦 带来了平台调度系统 ...

  6. Apache DolphinScheduler(海豚调度) - 1.3 系列核心表结构剖析

    Apache DolphinScheduler 是一个分布式去中心化,易扩展的可视化 DAG 工作流任务调度系统.致力于解决数据处理流程中错综复杂的依赖关系,使调度系统在数据处理流程中开箱即用. 近日 ...

  7. 本周六 Apache DolphinScheduler & Doris 将联合线上 Meetup

    活动背景 2020年,大数据成为国家基建的一个重要组成,大数据在越来越多的领域展现威力.随着大数据的应用场景越来越多,大家对数据的响应速度和数据加工工作流的方便程度也提出了更高的要求.在这种背景下,相 ...

  8. Apache DolphinScheduler新一代分布式工作流任务调度平台实战-上

    概述 定义 dolphinscheduler 官网地址 https://dolphinscheduler.apache.org/ dolphinscheduler GitHub地址 https://g ...

  9. Apache DolphinScheduler 3.0.0 正式版发布!

    ​  点亮 ️ Star · 照亮开源之路 GitHub:https://github.com/apache/dolphinscheduler   ​ 版本发布 2022/8/10 2022 年 8 ...

  10. 数据平台调度升级改造 | 从Azkaban 平滑过度到 Apache DolphinScheduler 的操作实践

    Fordeal的数据平台调度系统之前是基于Azkaban进行二次开发的,但是在用户层面.技术层面都存在一些痛点问题难以被解决.比如在用户层面缺少任务可视化编辑界面.补数等必要功能,导致用户上手难体验差 ...

随机推荐

  1. Linux下安装PHP环境

    Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` Linux下安装PHP环境 日期:2018-5-7 阿珏 ...

  2. windows server 安装.net framework 3.5失败

    windows server如果高版本的.net framework 那么在安装.net framework3.5时会提示已安装高版本的不能安装低版本的了 ---------------------- ...

  3. MongoDB文档存储

    非关系型数据库存储 NoSQL,全称 Not Only SQL,意为不仅仅是 SQL,泛指非关系型数据库.NoSQL 是基于键值对的,而且不需要经过 SQL 层的解析,数据之间没有耦合性,性能非常高. ...

  4. 我又学会了使用Range实现网络文件下载的断点续传

    目录 前言 1.Range请求头 1.1.概述 1.2.使用限制 1.3.范围请求 1.4.预防资源变更 2.断点续传下载实现 2.1.流程设计 2.2.代码实现 2.3.运行结果 3.RandomA ...

  5. Mysql 聚合函数嵌套使用

    Mysql 聚合函数嵌套使用 目的:Mysql 聚合函数嵌套使用 聚合函数不可以直接嵌套使用,比如: max(count(*)) 思路:但是可以嵌套子查询使用(先分组取出count值, 再将count ...

  6. 高通Android UEFI XBL 代码流程分析

    高通Android UEFI XBL 代码流程分析 背景 之前学习的lk阶段点亮LCD的流程算是比较经典,但是高通已经推出了很多种基于UEFI方案的启动架构. 所以需要对这块比较新的技术进行学习.在学 ...

  7. 实测14us,Linux-RT实时性能及开发案例分享—基于全志T507-H国产平台

    本文带来的是基于全志T507-H(硬件平台:创龙科技TLT507-EVM评估板),Linux-RT内核的硬件GPIO输入和输出实时性测试及应用开发案例的分享.本次演示的开发环境如下: Windows开 ...

  8. 【VMware vSAN】vSAN Data Protection Part 2:配置管理。

    上篇文章"vSAN Data Protection Part 1:安装部署."介绍了如何安装及部署 VMware Snapshot Service Appliance 设备,并在 ...

  9. [FLET] 02 route 测试

    from typing import Dict import flet from flet import AppBar, ElevatedButton, Page, Text, View, color ...

  10. JSON 的了解?

    1., JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.(为了和其他语言进行交互)2. 数据格式简单, 易于读写, 占用带宽小{'age':'12', ' ...