FileSystemConnector架构

1.排查思路

这个问题报到我这边的时候,有同学已经排查过一轮了。根据网上搜索,会告知你可能是yarn的压力过大、网络短暂不稳定等,可以调大heartbeat.timeout来缓解这个问题,经调整改问题并未解决。

另外一个说法会告知你是GC频繁的原因。建议调整内存,调整后,的确有一定的效果(使出问题的时间变慢)。那很显然和代码有关系了。

因为之前一个版本同步数据都没有出问题,因此开始寻找最近代码的改动,找了几圈下来并没有找到可疑的代码。顿时觉得有点头皮发麻。于是让现场的同学切换到上个版本继续做全量,现象依旧会发生。

这时我就有点怀疑生产环境的特性了——比如数据特性,但现场的同学告知我数据并没有什么特殊之处。于是我要了一份现场的HeapDump,丢到了分析软件上进行查看,发现org.apache.flink.streaming.api.functions.sink.filesystem.Bucket的对象特别多。

于是看了一下Bucket对象的定义:

/**
 * A bucket is the directory organization of the output of the {@link StreamingFileSink}.
 *
 * 

For each incoming element in the {@code StreamingFileSink}, the user-specified {@link * BucketAssigner} is queried to see in which bucket this element should be written to. */ @Internal public class Bucket {

好家伙。一个目录一个对象,此时此刻我已经对现场的同学告知我的“数据没有什么特殊之处”产生了怀疑,不过为了实锤,我还是跟了一遍代码:

|-- HiveTableSink
   \-- createStreamSink
|-- StreamingFileSink
  \-- initializeState
|-- StreamingFileSinkHelper
  \-- constructor
|-- HadoopPathBasedBulkFormatBuilder
  \-- createBuckets
|-- Buckets
  \-- onElement
  \-- getOrCreateBucketForBucketId

过了一遍代码以后,心里便有了数。问了下现场,同步的数据时间跨度是不是特别大,现场同学确认后,时间跨度为3年多。于是建议降低时间跨度,或者降低分区时间。最终将全量批次进行切分后解决了这个问题。

2. 解决问题后的好奇

如果每个目录都会产生一个Bucket,那如果运行一个流作业,岂不是迟早碰到相同的问题。这么显而易见的问题,社区的大神们肯定早就想到了,好奇心驱使着我寻找答案——直到看到了这段代码:

public void commitUpToCheckpoint(final long checkpointId) throws IOException {
        final Iterator>> activeBucketIt =
                activeBuckets.entrySet().iterator();

        LOG.info(
                "Subtask {} received completion notification for checkpoint with id={}.",
                subtaskIndex,
                checkpointId);

        while (activeBucketIt.hasNext()) {
            final Bucket bucket = activeBucketIt.next().getValue();
            bucket.onSuccessfulCompletionOfCheckpoint(checkpointId);

            if (!bucket.isActive()) {
                // We've dealt with all the pending files and the writer for this bucket is not
                // currently open.
                // Therefore this bucket is currently inactive and we can remove it from our state.
                activeBucketIt.remove();
                notifyBucketInactive(bucket);
            }
        }
    }

你可能感兴趣的:(java)