Flink开发项目中遇到的一些问题总汇(持续更新)

问题 解决:
1、(Constants.A, Constants.B) 是定位到具体配置
2、设置flink全局变量

env.getConfig.setGlobalJobParameters(C)

但是某些算子可能用到非全局变量中的一些配置例如:map、process中open 函数中的配置需要局部配置变量。
3、map和process的联系:
map方法不允许缺少数据,也就是原来多少条数据,处理后依然是多少条数据,只是用来做转换。
本次开发map函数用来将source流中的数据转换成json model 对象

.map(JsonUtil.fromJson[LogModel] _).setParallelism(dealParallelism)

为什么不在map中写逻辑规则,是因为map方法不允许缺少数据,数据不知道什么时候来数据调用map需要吃资源,采用process,可以懒加载???
process中:
events (流元素)
state (容错,一致性,只在Keyed Stream)
timers (事件时间和处理时间, 只在keyed stream)
eg:

  .process(new FProcess)

  class FProcess extends ProcessFunction[LogModel, (Object, Boolean)] {
   

    //mutable.HashSet可变的hashset
    val cmdSet: mutable.HashSet[String] = new mutable.HashSet[String]()

    override def open(parameters: Configuration): Unit = {
   
    //配置局部变量
      val globConf = getRuntimeContext.getExecutionConfig.getGlobalJobParameters.asInstanceOf[Configuration]
      val cmdStr = globConf.getString(Constants.D, "")
      val splits = cmdStr.split("\\|")
      for (cmd <- splits) {
   
        cmdSet.add(cmd)
      }
 
    }
    override def processElement(model: LogModel, ctx: ProcessFunction[LogModel, (Object, Boolean)]#Context,
                                out: Collector[(Object, Boolean)]): Unit = {
   

      val action = model.action
      if (action.length > 0) {
   
        breakable {
   
          for (cmd <- cmdSet) {
   
            if (action.contains(cmd)) {
   
              val entity = new E
              entity.setCmd()
              entity.setSourceIp(model.A)
              entity.setUserName(model.B)
              entity.setDestinationIp(model.C)
              entity.setWarnLevel(4)
              out.collect((entity, true))
              break()
            }
          }
        }

}

4、
E:RabbitMQ 中该模块的queue,类似kafka中的topic

val stream4A = env.addSource(new RMQSource(connectionConfig, E, false, new SimpleStringSchema()))    

5、个人理解:因为某些业务有时间限制,而数据源本身会因为网略等因素出现延迟等现象,采用时间戳得方式判断不够严谨,所以采用封装event采用判断事件发生的时间更加合理。

AssignerWithPeriodicWatermarks 周期性的生成watermark,生成间隔可配置,根据数据的eventTime来更新watermark时间
AssignerWithPunctuatedWatermarks 不会周期性生成watermark,只根据元素的eventTime来更新watermark。
当用EventTime和ProcessTime来计算时,元素本身都是不带时间戳的,只有以IngestionTime计算时才会打上进入系统的时间戳。

以下为AssignerWithPunctuatedWatermarks需要重写得两个方法

 override def checkAndGetNextWatermark(lastElement: LogModel, extractedTimestamp: Long): Watermark = {
   
    //设定一个10s的缓冲区
      new Watermark(extractedTimestamp - 10000)
    }

    override def extractTimestamp(element: LogModel, previousElementTimestamp: Long): Long = {
   
    //事件时间
      element.logTime
    }

无论何时一个特定的事件表明一个新的watermark可能需要被创建,都使用AssignerWithPunctuatedWatermarks来生成。
在这个类中Flink首先调用extractTimestamp(…)来为元素分配一个timestamp,然后立即调用该元素上的checkAndGetNextWatermark(…)方法。
checkAndGetNextWatermark(…)方法传入在extractTimestamp(…)方法中分配的timestamp,并决定是否需要生产watermark。一旦checkAndGetNextWatermark(…)返回一个非空的watermark并且watermark比前一个watermark大的话,这个新的watermark将会被发送。

6、Timestamp和Watermark的关系和区别:

指定时间戳(Assigning Timestamps)
为了使用eventtime,Flink需要知道事件的时间戳,也就是说数据流中的元素需要分配一个事件时间戳。
这个通常是通过抽取或者访问事件中某些字段的时间戳来获取的。
  时间戳的分配伴随着水印的生成,告诉系统事件时间中的进度。
  这里有两种方式来分配时间戳和生成水印:
    1、直接在数据流源中进行
    2、通过timestamp assigner和watermark generator生成:在Flink中,timestamp 分配器也定义了用来发射的水印。
  注意:timestamp和watermark都是通过从1970年1月1日0时0分0秒到现在的毫秒数来指定的。

有Timestamp和Watermark的源函数(Source Function with Timestamps And Watermarks)
数据流源可以直接为它们产生的数据元素分配timestamp,并且他们也能发送水印。
这样做的话,就没必要再去定义timestamp分配器了,需要注意的是:如果一个timestamp分配器被使用的话,由源提供的任何timestamp和watermark都会被重写。
  为了通过源直接为一个元素分配一个timestamp,源需要调用SourceContext中的collectWithTimestamp(…)方法。为了生成watermark,源需要调用emitWa

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值