簡體   English   中英

apache flink session支持

[英]apache flink session support

我正在調查Apache Flink Streaming,用於我們的ETL和機器學習平台。 我還沒想到的是如何將事件流式傳輸到“會話”中。 更具描述性:所有事件都包含會話ID,為了豐富數據,我需要將屬於會話的所有事件組合在一起。 請注意事件是連續流入的(因此沒有批量支持,之后您可以簡單地執行groupBy例如)

一種可能的解決方案是維護會話的LRU緩存並將所有傳入事件排序到其關聯會話。 然后,在每個會話不活動X分鍾后,可以從緩存中“關閉”或逐出會話。 問題是如何在多租戶系統中處理此緩存; flink是否具有分布式緩存的概念,還是包含某種智能負載均衡器,其中事件被定向到網格中的同一分區?

更一般地說:使用流式api建立會話支持的最佳方式(用例和陷阱)是什么? 這有可能嗎? 以及如何處理重放流? (即從事件流入不完整會話的特定時間點開始(即在時間點之前發生事件)

對任何反饋,想法和/或指針感興趣。

提前致謝

我創建了一個可能非常接近您需要的示例: https//gist.github.com/aljoscha/91b6422114eac814479f

我使用Tuple2<Integer,String>來模擬數據。 整數是會話ID,而String是我們鍵入 (分區)數據的字段。

我建議你先看看main()方法,在那里你看到程序的流程。 其他位是自定義窗口定義SessionWindow窗口分配器和SessionTrigger 這基本上實現了您建議的緩存的想法。 窗口根據指定的窗口和密鑰保存在緩沖區中。 觸發器觸發后,我們處理窗口並清除內容。

當觸發器接收到一個元素時,它將來會注冊一個計時器10秒鍾。 如果到那時沒有新元素到達,則觸發器將觸發。 如果新元素到達該時間窗口內,它將注冊一個新的定時器,這將取代舊定時器,因為觸發器一次只能有一個活動定時器。

此外,這使用所謂的處理時間窗口 這也可以根據事件時間 (即元素的時間戳)更改為觸發。

可以使用EventTimeSessionWindows從事件流中提取會話。 它組合了一個接一個地形成會話窗口的所有事件,直到它們之間的間隙大於指定的值。 如果流包含許多會話(可以在每個事件中由sessionId標識),則應首先按會話ID分組,以便分別為每個會話保持會話窗口。

在下面的代碼示例中,表單的事件

case class Event(
    createdat: Timestamp,
    session: String
)

變成了

case class SessionEvent(
    sessionId: String,
    start: Instant,
    end: Instant,
    `type`: String
)

當最近20分鍾沒有事件( sessionTimeout )時發出SessionEvent

// Apache Flink 1.1.4 with Kafka connector

import java.util.Properties

import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.assigners.ProcessingTimeSessionWindows
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.streaming.api.windowing.windows.TimeWindow
import org.apache.flink.streaming.connectors.kafka.{FlinkKafkaConsumer09, FlinkKafkaProducer09}
import org.apache.flink.streaming.util.serialization.SimpleStringSchema
import org.apache.flink.util.Collector

object Main extends App {

  val sessionTimeout = Time minutes 20
  val kafkaCluster = "localhost:9092"
  val inputTopic = "events"
  val outputTopic = "sessions"

  val env = StreamExecutionEnvironment.getExecutionEnvironment
  val properties = new Properties
  properties.setProperty("bootstrap.servers", kafkaCluster)
  properties.setProperty("group.id", "sessions")

  val consumer = new FlinkKafkaConsumer09[String](inputTopic, new SimpleStringSchema, properties)
  val producer = new FlinkKafkaProducer09[String](kafkaCluster, outputTopic, new SimpleStringSchema)

  val stream =
    env
      .addSource(consumer)
      .map(Formats.readEvent _)
      .keyBy(_.session)
      .window(ProcessingTimeSessionWindows withGap sessionTimeout)
      .apply[SessionEvent] {
        (key: String, window: TimeWindow, values: Iterable[Event], out: Collector[SessionEvent]) ⇒
          val session =
            SessionEvent(
              key,
              values.head.createdat.toInstant,
              values.last.createdat.toInstant,
              "end"
            )
          out.collect(session)
      }
      .map(Formats.writeSessionEvent _)
      .addSink(producer)

  env.execute("sessions")
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM