Flink学习6-常见问题

Flink学习6-常见问题

Flink系列文章

1 编译报错

flink no implicits found for parameter evidence9

  • 解释:缺少隐式转换。
  • 解决:在代码上加入import org.apache.flink.api.scala._即可

Error:(72, 8) value build is not a member of ?0

使用flink 1.10.0时报错,代码如下:

val sink: StreamingFileSink[String] = StreamingFileSink
      .forRowFormat(new Path(parameter.get("hdfs-path", "hdfs://xxx"))
        , new SimpleStringEncoder[String]("UTF-8"))
      .withBucketAssigner(new DateTimeBucketAssigner)
      .withRollingPolicy(OnCheckpointRollingPolicy.build())
      .build

报错详细信息:

Error:(72, 8) value build is not a member of ?0
possible cause: maybe a semicolon is missing before `value build'?
      .build

参见Change to StreamingFileSink in Flink 1.10

这是一个bug,已经在flink 1.10.1中解决。

2 启动报错

2.1 ClassCastException: cannot assign instance

使用bin/flink run -m yarn-cluster ...方式提交flink作业时,报错如下:

Caused by: java.lang.ClassCastException: cannot assign instance of org.apache.commons.collections.map.LinkedMap to field org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumerBase.pendingOffsetsToCommit of type org.apache.commons.collections.map.LinkedMap in instance of org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer010

经查,是因为
。我们提交的Flink作业,相关的class被动态加载。

可参考X cannot be cast to X exceptions

是因为多个不同版本的org.apache.commons.collections.map.LinkedMap被不同的CalssLoader加载,而这些类被尝试转换为对方。

解决方法是编辑conf/flink-conf.yaml,设置classloader.resolve-order: parent-first(flink默认逆置了ClassLoader,使用ChildClassLoader即user code ClassLoader来动态加载类。这个选项就关闭了逆置,即优先使用ParentClassLoader Java Application ClassLoader动态加载)来关闭逆置或设置classloader.parent-first-patterns-additional来单独设置使用parent-first的package。

2.2 ClassNotFoundException,NoSuchMethodError,NoClassDefoundError相关错误

  1. 检查maven scope
  2. 检查$FLINK_HOME/lib
  3. 检查jobmanager启动日志,看jar包加载顺序,是否有其他相关jar被优先加载,导致类冲突。如果是,把该包放到$FLINK_HOME/lib,会优先加载

3 运行报错

3.1 Jobmanager内存超限被Kill

之前我们设置的Jobmanager总内存大小为-yjm 2048m,实际JobManager Heap总大小为1399MB,其他内存还包括元空间、Direct Memory 、 栈、本地栈、程序计数器等部分。

在运行DataStream的StreamingFileSink(On Yarn)过程中,突然遇到整个应用直接挂掉的情况。具体在Yarn的FAILED中可以找到该应用记录,可以看到Diagnostics日志如下:

Application application_1575939577711_199999 failed 1 times (global limit =2; local limit is =1) due to Attempt recovered after RM restartAM Container for appattempt_1575939577711_199999_000001 exited with exitCode: -104

Failing this attempt.Diagnostics: Container [pid=994899,containerID=container_e28_1575939577711_199999_01_000001] is running beyond physical memory limits. Current usage: 2.0 GB of 2 GB physical memory used; 7.5 GB of 16 GB virtual memory used. Killing container.

Dump of the process-tree for container_e28_1575939577711_199999_01_000001 :
|- PID PPID PGRPID SESSID CMD_NAME USER_MODE_TIME(MILLIS) SYSTEM_TIME(MILLIS) VMEM_USAGE(BYTES) RSSMEM_USAGE(PAGES) FULL_CMD_LINE
|- 994935 994899 994899 994899 (java) 21450780 17798162 7969161216 524011 /usr/local/jdk//bin/java -Xms1448m -Xmx1448m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/test.bin -Dlog.file=/yarn/logs/application_1575939577711_199999/container_e28_1575939577711_199999_01_000001/jobmanager.log -Dlogback.configurationFile=file:logback.xml -Dlog4j.configuration=file:log4j.properties org.apache.flink.yarn.entrypoint.YarnSessionClusterEntrypoint
|- 994899 994897 994899 994899 (bash) 0 0 115818496 297 /bin/bash -c /usr/local/jdk//bin/java -Xms1448m -Xmx1448m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/test.bin -Dlog.file=/yarn/logs/application_1575939577711_199999/container_e28_1575939577711_199999_01_000001/jobmanager.log -Dlogback.configurationFile=file:logback.xml -Dlog4j.configuration=file:log4j.properties org.apache.flink.yarn.entrypoint.YarnSessionClusterEntrypoint 1> /yarn/logs/application_1575939577711_199999/container_e28_1575939577711_199999_01_000001/jobmanager.out 2> /yarn/logs/application_1575939577711_199999/container_e28_1575939577711_199999_01_000001/jobmanager.err

Container killed on request. Exit code is 143

Container exited with a non-zero exit code 143

For more detailed output, check the application tracking page: http://192.168.1.1:1111/cluster/app/application_1575939577711_199999 Then click on links to logs of each attempt.
. Failing the application.

随后点击该应用Logs查看:
在这里插入图片描述
最后,我们查了监控一直没找到原因(内存一直平稳并未达到2GB)。网上搜了很久也没找到出错原因。

于是我们从最后一次成功Checkpoint处恢复,调大了JobManager内存,继续观察。如果还发现问题回来补充。

4 API问题

4.1 DataStream

4.1.1 StreamingFileSink

可以参考 Flink学习-DataStream-HDFSConnector(StreamingFileSink)3.5 常见问题章节,有关于少类、找不到方法、中文乱码等问题描述

4.2 Table & Sql API

4.2.1 Flink 1.10 关键字time解析报错问题

按照reserved-keywords的说法,我们已经对关键字字段time加上了反引号``,但还是有问题,描述如下:

  1. ddl里面源表包含该字段 time bigint(13位毫秒时间戳),然后是ts_field AS TO_TIMESTAMP(FROM_UNIXTIME(time1 / 1000)),WATERMARK FOR ts_field AS ts_field - INTERVAL ‘10’ SECOND

  2. 再定义目标表。

  3. insert into 目标表 select TUMBLE_START(ts_field, INTERVAL ‘5’ SECOND) as tumble_start, TUMBLE_END(ts_field, INTERVAL ‘5’ SECOND) as tumble_end from 源表 GROUP BY TUMBLE(ts_field, INTERVAL ‘5’ SECOND);

类似如上,用ide调试代码会发现执行时会生成一个临时表,然后select time from 临时表,这个地方time已经不再带反引号了,会导致calcite解析报错,说遇到了time字段。。。

解决方案是自己改org.apache.flink.table.planner.calcite.CalciteParser#parse方法。

4.2.2 Flink 1.10 SQL API时区问题

我在使用时,发现时区全部加了8。。。导致我的时间戳全部变成了+8小时。

具体原因是Flink会大量使用org.apache.flink.table.dataformat.SqlTimestamp来转换时间。

比如我DDL中有字段如下:

time1 BIGINT,
ts_field AS TO_TIMESTAMP(FROM_UNIXTIME(time1 / 1000)),
WATERMARK FOR ts_field AS ts_field - INTERVAL '10' SECOND

则当消费一条time1为1587047085000的数据,则会调用SqlTimestamp#fromLocalDateTime(LocalDateTime dateTime)方法。

这个时候,时间已经被转为了不带时区的LocalDateTime,值为2020-04-16T22:24:45。看起来貌似还对,但是接下来就出问题了。看看这个fromLocalDateTime方法:

public static SqlTimestamp fromLocalDateTime(LocalDateTime dateTime) {
	// 这个地方转为了18368
	long epochDay = dateTime.toLocalDate().toEpochDay();
	// 这里是80685000000000,这个没问题
	long nanoOfDay = dateTime.toLocalTime().toNanoOfDay();
	
	// 毫秒数已经变成了+8小时的时间戳!
	long millisecond = epochDay * MILLIS_PER_DAY + nanoOfDay / 1_000_000;
	int nanoOfMillisecond = (int) (nanoOfDay % 1_000_000);

	return new SqlTimestamp(millisecond, nanoOfMillisecond);
}

通过上述代码,我们知道,flink内部将LocalDateTime转为了epochDay和nanoOfDay两部分。其中epochDay是日期部分减去1970年1月1日的天数。问题就在于,是当做UTC时间处理的,没有考虑我们现在的时区为东八区!

这样一来,日期部分的时间转换后就是2020-04-16 00:00:00(UTC),也就是2020-04-16 08:00:00(东八区时间)。自然,毫秒时间戳就比时间时间多了八小时(28800000毫秒)。这就是时区问题根源所在!

这个问题很难解决,个人觉得这个时间就应该将考虑时区后转换得到的时间戳作为统一的衡量标准来转换。

4.3 DataSet

参考文档

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值