并行度大于1时Flink作业执行失败,求助排查配置问题
我来帮你拆解下这个问题:你遇到的FileNotFoundException,本质是因为Flink默认的本地临时目录没法在多个TaskManager之间共享,而当你开启Exactly Once语义的Checkpoint、用RocksDB做状态后端,且并行度大于1时,跨TaskManager的状态交互会需要访问这些临时文件,导致报错。
为啥会出现这个问题?
当并行度设为1时,所有任务都跑在同一个TaskManager上,临时文件都在本地磁盘,自然没问题。但并行度大于1后,任务分散到不同的TaskManager节点,Flink的Checkpoint机制(尤其是Exactly Once模式)会涉及到跨节点的状态快照协调,而默认的/tmp/flink-io-xxx是每个TaskManager的本地目录,其他节点根本访问不到,所以就会抛出“文件找不到”的异常。
而禁用Checkpoint后,不会触发这种跨节点的临时文件访问,所以作业能正常跑起来。
你需要补充的几个配置
1. 把Flink的全局临时目录改成共享存储
这是最关键的一步,你需要将Flink的io.tmp.dirs配置为所有TaskManager都能读写的共享存储路径(比如HDFS、NFS,或者云环境里的共享挂载目录)。
- 方式一:修改集群的
flink-conf.yaml配置文件:io.tmp.dirs: hdfs://your-hdfs-cluster/flink-shared-tmp - 方式二:提交作业时通过命令行临时指定(不用重启集群):
注意要确保所有TaskManager节点对这个共享目录有读写权限。flink run -Dio.tmp.dirs=hdfs://your-hdfs-cluster/flink-shared-tmp your-job.jar
2. 优化RocksDB的本地临时目录(可选但推荐)
虽然你已经配置了RocksDB的远程Checkpoint存储路径,但RocksDB在生成快照时会先在本地写临时文件,再上传到远程。你可以通过state.backend.rocksdb.localdir指定一个单独的共享目录给RocksDB用,避免和全局临时目录混在一起:
state.backend.rocksdb.localdir: hdfs://your-hdfs-cluster/flink-rocksdb-tmp
3. 检查TaskManager的权限
别忘记确认所有TaskManager进程对上述共享目录有足够的读写权限,不然就算路径对了,也会因为权限不足创建或访问文件失败。
验证方法
改完配置后,要么重启Flink集群(如果改了flink-conf.yaml),要么用命令行参数重新提交作业,设置并行度大于1并开启Checkpoint,看看是不是不再报错了。
内容的提问来源于stack exchange,提问作者Harshith Bolar

