读取 Flink 快照信息

本文档介绍了如何使用Java脚本解析Apache Flink的检查点,通过读取元数据文件,详细分析各Operator的状态占用情况,并按大小排序显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、脚本编写 

package com.igg.flink.tool.test;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.core.memory.ByteArrayInputStreamWithPos;
import org.apache.flink.core.memory.DataInputViewStreamWrapper;
import org.apache.flink.runtime.checkpoint.OperatorState;
import org.apache.flink.runtime.checkpoint.OperatorSubtaskState;
import org.apache.flink.runtime.checkpoint.metadata.CheckpointMetadata;

import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Comparator;
import java.util.Map;
import java.util.PriorityQueue;

import static org.apache.flink.runtime.checkpoint.Checkpoints.loadCheckpointMetadata;

/**
 * @date 2021-10-21 18:27
 */
@Slf4j
public class FlinkSnapshotAnalyzer {
    public static final int ILLEGAL_INPUT_ARGUMENT = -1;
    public static final int ILLEGAL_METADATA_FILEPATH = -2;

    public static void main(String[] args) throws IOException {
        if (args.length == 0) {
            log.error("Please input a Flink snapshot path as the first argument");
            System.exit(ILLEGAL_INPUT_ARGUMENT);
        }

        String savepointDirectory = args[0];
        log.info("User has provided snapshot path {}", savepointDirectory);

        File metaFile = new File(savepointDirectory + File.separator + "_metadata");
        if (!metaFile.exists() || !metaFile.isFile()) {
            log.error("Metafile {} is not a file or does not exist", metaFile.getPath());
            System.exit(ILLEGAL_METADATA_FILEPATH);
        }

        byte[] bytes = FileUtils.readFileToByteArray(metaFile);
        DataInputStream in = new DataInputViewStreamWrapper(new ByteArrayInputStreamWithPos(bytes));
        CheckpointMetadata deserializedMetadata = loadCheckpointMetadata(in, FlinkSnapshotAnalyzer.class.getClassLoader(), metaFile.getAbsolutePath());

        log.info("\n\n=========== Summary ===========");
        log.info("Checkpoint ID: {}", deserializedMetadata.getCheckpointId());
        log.info("Master States: {}", deserializedMetadata.getMasterStates());
        log.info("Operator States: {}", deserializedMetadata.getOperatorStates());

        PriorityQueue<Tuple2<OperatorState, Long>> stateSizeQueue = new PriorityQueue<>(new OperatorStateSizeComparator());

        double totalStateSizes = 0;
        for (OperatorState operatorState : deserializedMetadata.getOperatorStates()) {
            long stateSizeForOperator = 0;
            for (Map.Entry<Integer, OperatorSubtaskState> entry : operatorState.getSubtaskStates().entrySet()) {
                totalStateSizes += entry.getValue().getStateSize();
                stateSizeForOperator += entry.getValue().getStateSize();
            }
            stateSizeQueue.add(new Tuple2<>(operatorState, stateSizeForOperator));
        }

        while (!stateSizeQueue.isEmpty()) {
            Tuple2<OperatorState, Long> operatorStateTuple = stateSizeQueue.poll();
            OperatorState operatorState = operatorStateTuple.f0;
            log.info("\n\n-> [{}%] {}MB Operator ID {}",
                    operatorStateTuple.f1 / totalStateSizes * 100,
                    operatorStateTuple.f1 / 1024 / 1024,
                    operatorState.getOperatorID());

            for (Map.Entry<Integer, OperatorSubtaskState> entry : operatorState.getSubtaskStates().entrySet()) {
                log.info("[{} MB] {}: Subtask States: {}",
                        entry.getValue().getStateSize() / 1024 / 1024,
                        entry.getKey(),
                        entry.getValue());
            }
        }
    }

    public static class OperatorStateSizeComparator implements Comparator<Tuple2<OperatorState, Long>> {
        @Override
        public int compare(Tuple2<OperatorState, Long> o1, Tuple2<OperatorState, Long> o2) {
            return Long.compare(o1.f1, o2.f1);
        }
    }
}

2、传入 checkpoint 路径,执行脚本

3、执行结果对各个 Operator 的状态占用空间进行了排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

magic_kid_2010

你的支持将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值