ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Linux下Kettle部署与crontab定时任务配置全攻略

Linux下Kettle部署与crontab定时任务配置全攻略 你有没有遇到过这种情况在Windows上把Kettle的ETL流程调得好好的测试数据跑了一遍又一遍都没问题结果一到Linux服务器上部署就各种翻车——要么JAVA_HOME没配好起不来要么crontab执行了但日志里啥也没有要么中文乱码直接让你的文件表名变成天书这篇文章就围绕“Linux部署Kettle并设置定时任务”这件事把我踩过的坑和验证过的方案完整拆一遍。内容面向的数据开发、运维或者刚接手ETL调度任务的同学不管你是第一次在服务器上装Kettle还是已经跑起来了但定时任务总出幺蛾子这篇都能给你一个可以直接照抄的作业。我默认你手头已经有一份调试好的ktr或kjb文件没有也没关系部署完之后我会讲怎么用命令行验证目标机器是CentOS 7.x或者Ubuntu 20.04内存建议不低于2GB磁盘留个10GB左右给日志和数据缓冲。下面我们直接进正题。1. 整体部署思路为什么非要把Kettle放到Linux上跑先说个我经常被问到的问题Kettle在Windows上跑得好好的双击 spoon.bat 就能打开图形界面拖拖拽拽就把数据抽完了为什么非要挪到Linux服务器上原因很简单ETL的任务本质是“稳定、自动、无人值守”。Windows图形界面适合做开发调试但很难做到7x24小时稳定调度。服务器重启了你要手动登录去再点一次运行凌晨两点的日报抽取任务失败了你总不能从被窝里爬起来开电脑点重跑吧。放到Linux上之后配合crontab或者更专业的调度工具任务的触发、重试、日志归档全都能自动化这才是生产环境该有的样子。整体部署链路其实不复杂核心就五步装好JDK并配置JAVA_HOMEKettle是Java程序这一步错了后面全白搭下载Kettle的发行包并解压到指定目录把用到的数据库驱动jar放进Kettle的lib目录用命令行方式验证是否能正常执行ktr/kjb写crontab定时任务并解决环境变量、日志输出、重复执行等问题每一步都有坑。我见过有人在第1步就卡了两天也见过有人第4步执行成功但第5步定时任务怎么都不触发最后发现是crontab里写死了错误的环境变量路径。下面我把每一步的关键细节都掰开揉碎讲清楚。2. 环境准备与Kettle安装版本匹配是头等大事2.1 JDK版本怎么选不是越新越好Kettle本身对JDK版本有明确要求这一点很多人会忽略。我最早在服务器上装的是JDK 11结果Kettle 8.2直接起不来报了一堆UnsupportedClassVersionError查了半天才发现是版本不兼容。根据我实际验证过的组合Kettle版本推荐JDK版本备注Kettle 7.1JDK 1.7或1.8老项目还在用新项目不建议Kettle 8.2 / 8.3JDK 1.8最稳妥的组合网上资料最多Kettle 9.0 / 9.1JDK 1.8或11我用的是JDK 1.8稳得很Kettle 9.3 / 9.4JDK 11或17新版对高版本JDK支持更好如果你拿不准该用哪个我的建议是如果是新部署直接用Kettle 9.3配JDK 11这个组合我跑了大半年没出过兼容性问题。如果是在老服务器上替换先确认现有JDK版本再选对应的Kettle版本别上来就装最新的否则可能连spoon.sh都起不来。安装JDK这一步就不赘述了只说两个容易忽略的点。第一安装完一定要执行java -version确认版本没错然后执行echo $JAVA_HOME确认环境变量生效。第二有些服务器上自带了OpenJDK但路径跟Oracle JDK不一样Kettle的启动脚本对JAVA_HOME的依赖很强最好在/etc/profile里显式写死不要依赖系统默认。# 在/etc/profile末尾追加 export JAVA_HOME/usr/local/jdk-11.0.21 export PATH$JAVA_HOME/bin:$PATH export CLASSPATH.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar # 使配置生效 source /etc/profile2.2 Kettle下载与解压记住这个目录规划下载地址我就不贴了搜索引擎搜“kettle下载”能找到官方源。需要注意两点一是Kettle的发行包有-SNAPSHOT后缀的版本这种是开发版稳定性没保障生产环境避开二是下载zip包之后解压文件名通常长这样pdi-ce-9.3.0.0-428.zip。解压这一步有一个高频坑中文乱码。有些Kettle的压缩包里包含中文文件和目录比如示例转换里的中文名称在Linux下用默认方式解压文件名直接变成乱码。我在热词榜里也看到“linux 解压文件乱码”这个搜索词上来了说明踩坑的人不少。解决方法是安装unzip工具并指定字符集# CentOS yum install -y unzip # Ubuntu apt-get install -y unzip # 解压时指定GBK编码Windows下压缩的zip常见编码 unzip -O GBK pdi-ce-9.3.0.0-428.zip -d /opt/kettle如果没有-O参数部分unzip版本不支持那就用Python的zipfile模块配合编码处理或者干脆用7z配合参数解压。我实测最简单的方式还是unzip -O GBK一次解决。解压完成后我习惯把目录结构调整成这样/opt/kettle/ ├── pdi-ce-9.3.0.0-428/ # Kettle主程序目录 ├── data/ # 存放数据文件、脚本 ├── etl/ # 存放ktr和kjb文件 │ ├── job/ # 作业文件 │ └── transform/ # 转换文件 └── logs/ # 日志目录后面crond输出会用到这样做的好处很直接数据文件、ETL脚本、日志三分离排查问题的时候不用在整个文件系统里翻来翻去。另外Kettle的转换里如果你用了相对路径比如读取某个文件那相对路径是相对于当前工作目录的所以执行kitchen.sh或pan.sh之前先cd到统一的工作目录就特别重要。这个习惯能帮你规避掉大量“明明文件存在但就是读不到”的诡异问题。2.3 目录权限一个坑了我一下午的问题Kettle解压完后一定记得把执行权限给到位chmod -R 755 /opt/kettle/pdi-ce-9.3.0.0-428/如果你是用root解压的而crontab计划任务是用普通用户执行的那普通用户可能连目录都进不去。我在生产环境踩过这个坑脚本手动执行一切正常但crontab里就是不干活后来用sudo -u etlUser pan.sh ...一跑才发现权限不足。为了避免这类问题我建议专门创建一个运行Kettle的系统用户比如etluser然后把整个Kettle目录的属主改给它useradd -m -s /bin/bash etluser chown -R etluser:etluser /opt/kettle/后面所有手动验证、crontab配置都用这个用户不要用root跑ETL。从安全角度说ETL任务涉及数据库连接串、账号密码用普通用户能降低凭据泄露和误操作的风险这个习惯值得养成。3. 数据库驱动与连接配置不装驱动一切白搭3.1 驱动的本质Kettle只是个壳干活的是JDBC很多人第一次在Linux上跑通Kettle后发现连不上数据库第一反应是网络问题或账号问题排查了一圈最后发现是驱动jar包没装。Kettle本身的安装包只带了少数几个数据库的驱动而且版本往往偏旧像MySQL、PostgreSQL、达梦、人大金仓这些常用的通常需要自己下载对应版本的JDBC驱动jar包放到Kettle的lib目录下然后重启或者重新执行命令行才能生效。驱动的版本匹配有一条黄金法则驱动版本尽量跟数据库服务端版本保持一致或者比服务端版本更兼容。以MySQL为例MySQL 5.7用mysql-connector-java-5.1.49.jar没问题但MySQL 8.0再用老驱动就会报Public Key Retrieval is not allowed或者时区相关的错误这时候换成mysql-connector-j-8.0.33.jar新版的命名里少了个java就正常了。放驱动时注意jar包文件名不要有中文路径不要有空格否则classpath加载时会出幺蛾子。然后记得chmod 644 /opt/kettle/pdi-ce-9.3.0.0-428/lib/mysql-connector-j-8.0.33.jar chown etluser:etluser /opt/kettle/pdi-ce-9.3.0.0-428/lib/mysql-connector-j-8.0.33.jar3.2 JNDI配置让连接信息不再散落在转换里大家在Windows上调试Kettle时数据库连接一般是直接配在转换里的这种方式的优点是简单直接缺点是当你把转换文件挪到Linux服务器上时要么在服务器上打开Spoon重新配一遍要么就得小心翼翼地改XML文件里的连接串稍有不慎就出错。Kettle很早就提供了JNDI方式管理数据库连接。做法是编辑simple-jndi/jdbc.properties这个文件。比如我要配一个名为mysql_etl的JNDI数据源mysql_etl/typejavax.sql.DataSource mysql_etl/drivercom.mysql.cj.jdbc.Driver mysql_etl/urljdbc:mysql://192.168.1.100:3306/etl_db?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue mysql_etl/useretl_user mysql_etl/passwordYourPassword然后在转换里的数据库连接类型选择“JNDI”名称填mysql_etlKettle就会自动从jdbc.properties里读取配置。这样做的最大好处是转换文件里不暴露数据库密码而且切换环境时只需要改这一个配置文件不用打开几百个转换一个个替换连接。JNDI配置里URL的参数也值得多说几句。useUnicodetruecharacterEncodingUTF-8这个参数对中文数据非常重要不加它从MySQL抽出中文到目标库经常变成问号。serverTimezone指定时区MySQL 8.0以后不指定会报时区错误。useSSLfalse是测试环境常用的生产环境如果有SSL要求需要按实际情况调整别图省事直接关。3.3 一个容易被忽略的坑驱动类型变了类名也变了MySQL 5.x的驱动类名是com.mysql.jdbc.DriverMySQL 8.x的驱动类名是com.mysql.cj.jdbc.Driver。你在Kettle里配置连接时如果选的是“MySQL”Kettle可能还会自动填老类名但驱动换成8.x的jar后老类名也能加载8.x兼容只是会打一行warning日志。这个warning不影响使用但强迫症患者看着难受。如果你用的是PostgreSQL驱动类名是org.postgresql.DriverURL是jdbc:postgresql://ip:port/dbname。国产数据库这块达梦的驱动类名是dm.jdbc.driver.DmDriver人大金仓是com.kingbase8.Driver。这些细节在Windows上调通之后一般不会出问题但换到Linux新环境重新配JNDI时容易手滑建议配完先用命令行测试别急着上定时任务。4. 命令行执行ktr/kjb这是定时任务的执行基础4.1 pan.sh 和 kitchen.sh 的区别与参数Kettle提供了两个命令行工具pan.sh执行转换文件ktr也就是ETL的数据流部分比如读文件、查表、转换、写表kitchen.sh执行作业文件kjb作业里可以嵌套多个转换还可以做条件判断、邮件通知、跑SQL脚本这两者的关系可以类比成转换是“干活的人”作业是“项目管理”。定时任务调度的时候调度入口通常是作业kjb因为你可以把日志清空、错误处理、重跑机制都挂在作业层面。命令行基本用法# 执行转换 /opt/kettle/pdi-ce-9.3.0.0-428/pan.sh -file/opt/kettle/etl/transform/your_transform.ktr -levelBasic -logfile/opt/kettle/logs/transform_$(date %Y%m%d).log # 执行作业 /opt/kettle/pdi-ce-9.3.0.0-428/kitchen.sh -file/opt/kettle/etl/job/your_job.kjb -levelDetailed -logfile/opt/kettle/logs/job_$(date %Y%m%d).log参数说明参数作用我的建议-file指定ktr/kjb文件的绝对路径强烈建议用绝对路径别用相对路径-level日志级别Error、Basic、Detailed、Debug、Rowlevel平时用Basic排查问题时用Debug或Rowlevel-logfile指定日志输出文件配合日期参数方便日志归档-param传入命名参数比如-param:TABLE_NAMEods_user-listdir列出目录一般不常用远程调试时会用到4.2 命名参数和时间参数让同一个转换适配不同日期上面提到了-param这是Kettle做增量抽取和定时任务的灵魂。假设你要每天抽取前一天的数据那你的SQL里应该写成SELECT * FROM orders WHERE create_date ${ETL_DATE}然后在执行kitchen.sh时传入/opt/kettle/pdi-ce-9.3.0.0-428/kitchen.sh -file/opt/kettle/etl/job/daily_orders.kjb -param:ETL_DATE$(date -d yesterday %Y-%m-%d) -levelBasic -logfile/opt/kettle/logs/daily_job_$(date %Y%m%d).log这里的关键是在Kettle的转换里正确引用参数。很多人在Windows的Spoon里调试时就卡在这里参数明明传了但转换里读不到。原因多半是变量作用域没有设置对。在SQL脚本那个步骤里你要在“变量替换”相关的选项中勾选允许替换变量否则${ETL_DATE}会被当成字面量拼进SQL里查出来的数据铁定不对。另外Kettle内置的日期变量也可以直接用比如${__DATE__}是当前日期${__PREVIOUS_DAY__}是前一天${__MONTH_BEGIN__}是月初。这些内置变量在某些场景下省去了手动传参的麻烦但我个人习惯还是用自定义命名参数因为可读性好而且不容易踩时区的坑。4.3 首次执行的验证方法手动先跑通再上定时配置好环境和文件后一定要先手动执行一次。这一步是排查问题的黄金时间因为你可以在终端里直接看到完整输出。我常用的验证步骤先切换到etluser用户确保权限吻合su - etluser执行kitchen.sh日志级别先调到Debug-levelDebug在输出里观察是否有Exception、Error、Warn关键字确认数据落库后调整日志级别到Basic再跑一次确认正常检查日志文件生成时间、大小确认日志归档正常这五步走完才轮到配置crontab。千万别跳过手动验证直接上定时否则你连错误发生在哪一步都看不出来——是环境变量丢了还是路径不对是数据库连不上还是SQL写错了日志里能告诉你答案但前提是你得先把程序跑到能产生日志的地步。5. crontab定时任务配置让ETL自动化起来5.1 crontab基础语法与常见误区Linux的定时任务最常用的就是crontab基本语法是五个时间字段加一条命令分 时 日 月 周 命令比如每天凌晨2点30分执行30 2 * * * /opt/kettle/run_daily_etl.sh /opt/kettle/logs/cron.log 21这里我强烈建议你不要直接写kitchen.sh的长命令到crontab里而是把命令封装成一个shell脚本然后在crontab里调用这个脚本。理由有三点第一crontab环境变量极少它的PATH默认可能只有/usr/bin:/bin而你装JDK、Kettle的路径通常不在里面。直接调用kitchen.sh脚本里的 java 命令很可能直接报 command not found。封装成shell脚本后你可以在脚本里显式source/etc/profile从根源上解决。第二如果数据库连接串或者Kettle路径要调整直接改脚本就行不用改动crontab条目管理成本低。第三可以在shell脚本里加入一些额外的逻辑比如判断前一天是否执行成功失败则重试或者清理过期日志文件。一个我生产环境在用的脚本模板#!/bin/bash # daily_etl_job.sh # 每天凌晨执行的Kettle作业 export JAVA_HOME/usr/local/jdk-11.0.21 export PATH$JAVA_HOME/bin:$PATH # 定一个基础路径后面所有路径都基于它 BASE_DIR/opt/kettle KETTLE_HOME$BASE_DIR/pdi-ce-9.3.0.0-428 LOG_DIR$BASE_DIR/logs # 当前日期和昨天的日期用于日志命名和参数传递 TODAY$(date %Y%m%d) YESTERDAY$(date -d yesterday %Y-%m-%d) LOG_FILE$LOG_DIR/daily_job_${TODAY}.log # 切换到统一工作目录避免相对路径问题 cd $BASE_DIR/etl/job # 执行作业 $KETTLE_HOME/kitchen.sh \ -file$BASE_DIR/etl/job/daily_orders.kjb \ -param:ETL_DATE${YESTERDAY} \ -levelBasic \ -logfile${LOG_FILE} # 检查退出码 if [ $? -eq 0 ]; then echo $(date %Y-%m-%d\ %H:%M:%S) ETL job finished successfully. $LOG_FILE else echo $(date %Y-%m-%d\ %H:%M:%S) ETL job FAILED, check log for details. $LOG_FILE # 这里可以接上告警命令比如 curl 一个监控平台的接口发送告警 fi然后给脚本加执行权限chmod x /opt/kettle/scripts/daily_etl_job.sh最后编辑crontabcrontab -e -u etluser # 每天凌晨2点30分执行 30 2 * * * /opt/kettle/scripts/daily_etl_job.sh5.2 crontab环境变量90%的定时任务失败都栽在这里我前面提到crontab的环境变量很少这里展开说几个实际遇到的细节。第一个坑crontab里找不到java命令。通过crontab执行脚本时脚本里虽然export了JAVA_HOME但如果脚本开头没有source /etc/profile或. /etc/profile某些Linux发行版下环境变量依然不会加载因为crontab的shell不是登录shell不会自动加载profile。所以我的建议是在脚本第一行加上. /etc/profile不要觉得多余这一行能解决你一半的“crontab里怎么就不行”的问题。第二个坑crontab里百分号需要转义。比如你写-param:ETL_DATE$(date -d yesterday %Y-%m-%d)在shell里没问题但在crontab里%有特殊含义表示换行必须写成\%。这也是我建议把完整命令封装到脚本里的另一个原因——脚本里写%完全不用转义不用care这个坑。第三个坑crontab执行时间与预期不符。很多服务器时区是UTC或其他时区你本地是北京时间但服务器上的date命令显示的可能是UTC时间凌晨2点跑的任务实际上北京时间上午10点才跑日期都过了。排查定时任务前先执行date看看服务器时间对不对不对的话要先校准时区。5.3 防止任务重复执行文件锁比数据库锁更实在定时任务配好后你可能会遇到一个经典问题上一次任务还没跑完下一次调度时间又到了两个实例同时跑同一个转换数据库被写了两份重复数据。在集群调度场景下大家会想到用Redis分布式锁但单机Linux环境下我推荐一个轻量级方案flock文件锁。在shell脚本里加一段#!/bin/bash # 文件锁防止重复执行 LOCK_FILE/tmp/kettle_daily_etl.lock # 使用flock实现单实例运行如果拿不到锁直接退出 exec 200$LOCK_FILE flock -n 200 || { echo Another instance is running, exit.; exit 1; } # 自此以下放原来的逻辑 . /etc/profile export JAVA_HOME/usr/local/jdk-11.0.21 export PATH$JAVA_HOME/bin:$PATH ...原理很简单当脚本A拿住200号文件描述符的锁时脚本B再想拿锁会失败于是直接退出不会重复执行。这个方案在单机场景下比数据库锁、Redis锁简单可靠得多而且不依赖外部组件。5.4 日志清理如果你不想半年后磁盘爆掉Kettle的日志如果每天一个文件一年下来也就365个单个日志文件可能几十MB到几百MB不等。日志多的项目半年就能吃掉好几个GB磁盘空间。所以我建议在crontab里加一条每周清理的日志归档任务0 3 * * 1 find /opt/kettle/logs -name *.log -mtime 30 -exec rm -f {} \;每周一凌晨3点删除30天以前的日志文件。如果公司有日志平台要求保留更长时间那建议把日志文件按月份归档压缩比如tar -czf logs_202406.tar.gz logs/*.log再清理。这些细节看着不起眼但真到磁盘告警时能救你一命。6. 实战案例多表合并抽取到一个表附完整命令这里我不讲空理论直接拆解一个我在生产环境做过的需求每天凌晨把三张业务表订单表、退款表、售后表合并抽取到一张大宽表里供BI报表使用。先看转换ktr里做了什么三个“表输入”步骤分别从三张业务表读取增量数据SQL里用${ETL_DATE}过滤日期后面接“追加流”或“合并记录”步骤把三个数据流合并再到“字段选择”步骤统一字段类型和名称最后用“表输出”步骤写入目标宽表然后建一个作业kjb里面按顺序调用这个转换并定义一个“START”节点设置定时触发。把这个kjb保存为merge_biz_to_warehouse.kjb。Linux上的调度脚本命名为merge_daily_etl.sh#!/bin/bash . /etc/profile BASE_DIR/opt/kettle KETTLE_HOME$BASE_DIR/pdi-ce-9.3.0.0-428 LOG_DIR$BASE_DIR/logs YESTERDAY$(date -d yesterday %Y-%m-%d) LOG_FILE$LOG_DIR/merge_daily_${YESTERDAY}.log # 文件锁防止重复执行 LOCK_FILE/tmp/kettle_merge_etl.lock exec 200$LOCK_FILE flock -n 200 || { echo Another merge_job is running, exit.; exit 1; } # 执行Kettle作业 cd $BASE_DIR/etl/job $KETTLE_HOME/kitchen.sh \ -file$BASE_DIR/etl/job/merge_biz_to_warehouse.kjb \ -param:ETL_DATE${YESTERDAY} \ -levelBasic \ -logfile${LOG_FILE} EXIT_CODE$? if [ $EXIT_CODE -ne 0 ]; then # 错误时写专门错误日志后续可以做异常告警 echo $(date %F %T) merge job failed with exit code $EXIT_CODE $LOG_DIR/error.log fi # 只有正常结束时才清理锁文件其实flock不需要手动清理进程结束锁自动释放 exit $EXIT_CODE对应的crontab20 2 * * * /opt/kettle/scripts/merge_daily_etl.sh这里有个经验crontab时间设置不要卡在整点整分。数据库的备份任务、其他ETL任务也常在凌晨2点触发如果你的任务跟别人的任务同时跑数据库连接数瞬间飙高Kettle提取慢甚至会让数据库负载升高影响业务。错峰10-20分钟执行能省去很多和环境里其他任务“抢资源”的烦恼。7. 常见问题与排查技巧实录7.1 Kettle启动报错问题速查表症状可能原因排查与解决UnsupportedClassVersionErrorJDK版本过新或过旧与Kettle版本不兼容按第2.1节对照表换JDK版本Error: JAVA_HOME is not defined correctlyJAVA_HOME路径配置错误或crontab环境变量没加载执行echo $JAVA_HOME在脚本开头. /etc/profileDriver class not foundJDBC驱动jar没放进lib目录或类名配置错误检查lib目录下是否有对应驱动jar检查驱动类名是否与数据库版本匹配Public Key Retrieval is not allowedMySQL 8.0 老驱动或URL缺少allowPublicKeyRetrieval参数换新驱动在URL中加allowPublicKeyRetrievaltrue中文乱码zip解压编码不对或数据库连接URL缺少字符集参数解压用unzip -O GBKURL加characterEncodingUTF-8Unable to get connection from database网络不通、账号密码错、防火墙拦截先用命令行客户端测试数据库连通性再查Kettle配置7.2 crontab常见问题执行了但没结果这是我最常被问到的问题crontab明明配置了日志也显示执行了但Kettle的日志文件里啥都没有。我把这个问题的排查路径整理成一套标准动作先确认crontab已加载crontab -l -u etluser看cron服务的状态systemctl status crondCentOS或systemctl status cronUbuntu把脚本里的输出重定向到文件观察是否真的执行了30 2 * * * /opt/kettle/scripts/daily_etl_job.sh /tmp/cron_debug.log 21曾经有一次我的任务怎么都不触发排查了一圈发现是crontab文件里出现了不可见字符crontab -l看起来正常但实际执行不了。最后我用cat -A查看crontab文件才发现里面混入了Windows换行符^M$导致语法无法解析。这是因为我在Windows上编辑了crontab文件再上传到服务器的。很多年没用过这种方式了现在写crontab一律在服务器上用vim直接编辑这个坑就再也没出现过。7.3 内存溢出Kettle也是会OOM的Kettle作为Java程序默认的堆内存可能只有几百MB。当你抽取大批量数据时百万级甚至千万级会经常遇到OutOfMemoryError: Java heap space。如果你已经在日志里看到这条报错说明该调大内存了。Kettle的启动脚本里可以设置内存参数在kitchen.sh或pan.sh中修改PENTAHO_DI_JAVA_OPTIONSexport PENTAHO_DI_JAVA_OPTIONS-Xms512m -Xmx2048m -Dfile.encodingUTF-8我的经验值是单次抽取100万行以内-Xmx1024m够用500万行以上直接给到-Xmx4096m。但这也要看服务器物理内存别一台2G内存的机器硬给4G堆那起不来的。另外Kettle里有几个地方能缓解内存压力多使用“流式”处理方式避免“表输入”一次性加载全量数据在SQL里加分页条件分批读取尽量使用“数据库批量插入”而不是逐行插入。这些优化比单纯加内存更本质。7.4 kettle.log和调试日志如何快速定位问题行Kettle的日志级别里Rowlevel会把每一行数据的前缀都打印出来数据量大的时候日志文件几秒钟就能写上GB。所以除非是在排查某一行数据为什么丢失否则不要在生产环境用Rowlevel。我一般用两个组合正常调度时用-levelBasic只记录每个步骤的“起止”和“错误信息”排查问题时临时跑一次-levelDebug把详细执行计划、SQL语句、读取行数都打出来。另外Kettle管道里某个步骤出错时它的错误信息可能淹没在海量日志中。我命令行执行时会加一个参数-logfile/opt/kettle/logs/daily_job.log -levelBasic -logpipe/opt/kettle/logs/pipe.log-logpipe用于单独输出管道数据跟普通日志隔离开。这样定位问题的时候先看pipe.log里最后落库的行数再回到主日志里找报错位置效率能提高不少。8. 部署完成后的稳定性维护Kettle不停服的小技巧任务跑起来之后还有一个问题可能会让你头疼Kettle跑了一段时间后明明数据库连接池配置没问题但日志里开始出现连接超时、连接被重置的报错。这多半是数据库端把空闲连接断掉了而Kettle侧还拿着旧连接不放。我的经验是给数据库连接串加上几个参数...autoReconnecttruefailOverReadOnlyfalseconnectTimeout5000socketTimeout60000autoReconnecttrue让MySQL在连接失效后自动重连。socketTimeout设成60秒避免某个SQL卡死时线程无限期挂起。这些参数不一定能根治所有连接问题但能显著降低偶发性断连的概率。另外一个容易被忽视的是系统时钟。定时任务强烈依赖服务器时间如果服务器时钟漂移凌晨的任务可能在中午才跑。建议统一用chrony或ntp做时间同步这属于基础设施的范畴但确实会影响Kettle定时任务的可靠性。我遇到过一次因为服务器时间快了三分钟任务提前触发而数据库里的时间字段还没更新到当天导致抽取窗口错位最后对账才发现。这个教训我至今记得。最后聊一下版本升级。Kettle 9.x以后PDI还在持续更新新版本通常会修复一些已知bug和连接器兼容问题但升级也不是没有成本。我个人的习惯是生产环境不追新部署的Kettle版本至少在线上稳定运行一个月以上再考虑升级。升级前做好备份整个pdi目录打包然后先在测试环境跑一遍所有核心作业确认没问题再切换。ETL这种底层的系统稳定压倒一切。这篇文章就是我自己实际踩坑得到的经验汇总。希望能帮你在Linux上把Kettle跑得顺顺利利少走那些我走过的弯路。如果你部署的时候遇到什么奇奇怪怪的问题欢迎留言交流我看到了会回复。
返回列表