package com
import java.util
import org.apache.flink.cep.{PatternSelectFunction, PatternTimeoutFunction}
import org.apache.flink.cep.scala.{CEP, PatternStream}
import org.apache.flink.cep.scala.pattern.Pattern
import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.time.Time
//订单超时事件处理 超时事件报警
object OrderTimeout {
//输入样例类
package com
import com.OrderTimeout.OrderEvent
import org.apache.flink.api.common.state.{ValueState, ValueStateDescriptor}
import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.functions.co.{CoProcessFunction, KeyedCoProcessFunction}
import org.apache.flink.streaming.api.scala._
import org.apache.flink.util.Collector
//匹配两条流
object TxMatch {
//支付事件
case class OrderEvent(orderId:Long,enentType:String,txId:String,timestamp:Long)
//到账事件
case class ReceiptEvent(txId:String,payChannel:String,timestamp:Long)
def main(args: Array[String]): Unit = {
val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
//0.得到数据源
val orderinputStream: DataStream[String] = env.readTextFile(“F:\UserBehaviorAnalysis\OrderPayDetect\src\main\resources\OrderLog.csv”)
//读取订单事件
val orderEvert= orderinputStream.map(data => {
val arr = data.split(",")
OrderEvent(arr(0).toLong, arr(1), arr(2), arr(3).toLong)
}).assignAscendingTimestamps(.timestamp * 1000L).filter(.enentType==“pay”).keyBy(.txId)
//读取到账事件
val receiptStream: DataStream[String] = env.readTextFile(“F:\UserBehaviorAnalysis\OrderPayDetect\src\main\resources\ReceiptLog.csv”)
val receiptEvent= receiptStream.map(data => {
val arr = data.split(",")
ReceiptEvent(arr(0), arr(1), arr(2).toLong)
}).assignAscendingTimestamps(.timestamp * 1000L).keyBy(_.txId)
//合流操作
//connect
//join
val connectionStream: ConnectedStreams[OrderEvent, ReceiptEvent] = orderEvert.connect(receiptEvent)
val resultStream: DataStream[(OrderEvent, ReceiptEvent)] = connectionStream.process(new TxPayMatchResult)
resultStream.print(“match”)
resultStream.getSideOutput(new OutputTagOrderEvent).print(“unpay”)
resultStream.getSideOutput(new OutputTagReceiptEvent).print(“onmathc”)
env.execute(“TxMatch”)
}
class TxPayMatchResult extends CoProcessFunction[OrderEvent,ReceiptEvent,(OrderEvent,ReceiptEvent)]{
// 定义状态,保存当前交易对应的订单支付事件和到账事件
lazy val payEventState: ValueState[OrderEvent] = getRuntimeContext.getState(new ValueStateDescriptor[OrderEvent](“pay”, classOf[OrderEvent]))
lazy val receiptEventState: ValueState[ReceiptEvent] = getRuntimeContext.getState(new ValueStateDescriptor[ReceiptEvent](“receipt”, classOf[ReceiptEvent]))
// 侧输出流标签
val unmatchedPayEventOutputTag = new OutputTagOrderEvent
val unmatchedReceiptEventOutputTag = new OutputTagReceiptEvent
override def processElement1(pay: OrderEvent, ctx: CoProcessFunction[OrderEvent, ReceiptEvent, (OrderEvent, ReceiptEvent)]#Context, out: Collector[(OrderEvent, ReceiptEvent)]): Unit = {
// 订单支付来了,要判断之前是否有到账事件
val receipt = receiptEventState.value()
if( receipt != null ){
// 如果已经有receipt,正常输出匹配,清空状态
out.collect((pay, receipt))
receiptEventState.clear()
payEventState.clear()
} else{
// 如果还没来,注册定时器开始等待5秒
ctx.timerService().registerEventTimeTimer(pay.timestamp * 1000L + 5000L)
// 更新状态
payEventState.update(pay)
}
}
override def processElement2(receipt: ReceiptEvent, ctx: CoProcessFunction[OrderEvent, ReceiptEvent, (OrderEvent, ReceiptEvent)]#Context, out: Collector[(OrderEvent, ReceiptEvent)]): Unit = {
// 到账事件来了,要判断之前是否有pay事件
val pay = payEventState.value()
if( pay != null ){
// 如果已经有pay,正常输出匹配,清空状态
out.collect((pay, receipt))
receiptEventState.clear()
payEventState.clear()
} else{
// 如果还没来,注册定时器开始等待3秒
ctx.timerService().registerEventTimeTimer(receipt.timestamp * 1000L + 3000L)
// 更新状态
receiptEventState.update(receipt)
}
}
override def onTimer(timestamp: Long, ctx: CoProcessFunction[OrderEvent, ReceiptEvent, (OrderEvent, ReceiptEvent)]#OnTimerContext, out: Collector[(OrderEvent, ReceiptEvent)]): Unit = {
// 定时器触发,判断状态中哪个还存在,就代表另一个没来,输出到侧输出流
if( payEventState.value() != null ){
ctx.output(unmatchedPayEventOutputTag, payEventState.value())
}
if( receiptEventState.value() != null ){
ctx.output(unmatchedReceiptEventOutputTag, receiptEventState.value())
}
// 清空状态
receiptEventState.clear()
payEventState.clear()
package com
import org.apache.flink.api.common.state.{ValueState, ValueStateDescriptor}
import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.functions.co.{CoProcessFunction, ProcessJoinFunction}
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.util.Collector
//匹配两条流
object TxMatchWithJoin {
//支付事件
case class OrderEvent(orderId:Long,enentType:String,txId:String,timestamp:Long)
//到账事件
case class ReceiptEvent(txId:String,payChannel:String,timestamp:Long)
def main(args: Array[String]): Unit = {
val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
//0.得到数据源
val orderinputStream: DataStream[String] = env.readTextFile(“F:\UserBehaviorAnalysis\OrderPayDetect\src\main\resources\OrderLog.csv”)
//读取订单事件
val orderEvert= orderinputStream.map(data => {
val arr = data.split(",")
OrderEvent(arr(0).toLong, arr(1), arr(2), arr(3).toLong)
}).assignAscendingTimestamps(.timestamp * 1000L).filter(.enentType==“pay”).keyBy(.txId)
//读取到账事件
val receiptStream: DataStream[String] = env.readTextFile(“F:\UserBehaviorAnalysis\OrderPayDetect\src\main\resources\ReceiptLog.csv”)
val receiptEvent= receiptStream.map(data => {
val arr = data.split(",")
ReceiptEvent(arr(0), arr(1), arr(2).toLong)
}).assignAscendingTimestamps(.timestamp * 1000L).keyBy(_.txId)
//合流操作
//connect
//join
val result: DataStream[(OrderEvent, ReceiptEvent)] = orderEvert.intervalJoin(receiptEvent)
.between(Time.seconds(-3), Time.seconds(5))
.process(new TxMatchWithJoinResult())
result.print(“匹配成功”)
env.execute(“TxMatch”)
}
class TxMatchWithJoinResult() extends ProcessJoinFunction[OrderEvent,ReceiptEvent,(OrderEvent,ReceiptEvent)]{
override def processElement(left: OrderEvent, right: ReceiptEvent, ctx: ProcessJoinFunction[OrderEvent, ReceiptEvent, (OrderEvent, ReceiptEvent)]#Context, out: Collector[(OrderEvent, ReceiptEvent)]): Unit = {
out.collect(left,right)
}
package com
import java.util
import org.apache.flink.api.common.state.{ValueState, ValueStateDescriptor}
import org.apache.flink.cep.scala.pattern.Pattern
import org.apache.flink.cep.scala.{CEP, PatternStream}
import org.apache.flink.cep.{PatternSelectFunction, PatternTimeoutFunction}
import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.functions.KeyedProcessFunction
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.util.Collector
//订单超时事件处理
object OrderTimeoutWithState {
case class OrderEvent(orderId:Long,enentType:String,txId:String,timestamp:Long)
case class OrderResult(orderId:Long,resultMsg:String)
def main(args: Array[String]): Unit = {
val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
//0.得到数据yuan
val inputStream: DataStream[String] = env.readTextFile(“F:\UserBehaviorAnalysis\OrderPayDetect\src\main\resources\OrderLog.csv”)
val orderEventStream: KeyedStream[OrderEvent, Long] = inputStream.map(data => {
val arr = data.split(",")
OrderEvent(arr(0).toLong, arr(1), arr(2), arr(3).toLong)
}).assignAscendingTimestamps(.timestamp * 1000L)
.keyBy(.orderId)
val result: DataStream[OrderResult] = orderEventStream.process(new OrderPayMatchResult())
result.print(“payed”)
result.getSideOutput(new OutputTag[OrderResult]("timeout")).print("timeout")
env.execute()
}
class OrderPayMatchResult() extends KeyedProcessFunction[Long,OrderEvent,OrderResult]{
//定义状态
//1.如果pay来了 判断create来没
lazy val isCreateState: ValueState[Boolean] = getRuntimeContext.getState(new ValueStateDescriptor[Boolean]("is-create",classOf[Boolean]))
lazy val isPayedState: ValueState[Boolean] = getRuntimeContext.getState(new ValueStateDescriptor[Boolean]("is-payed",classOf[Boolean]))
lazy val timerTsState: ValueState[Long] = getRuntimeContext.getState(new ValueStateDescriptor[Long]("ts",classOf[Long]))
//
lazy val orderTimeoutOutputTag = new OutputTag[OrderResult]("timeout")
override def processElement(value: OrderEvent, ctx: KeyedProcessFunction[Long, OrderEvent, OrderResult]#Context, out: Collector[OrderResult]): Unit = {
val isCreate: Boolean = isCreateState.value()
val isPay: Boolean = isPayedState.value()
val timeTs: Long = timerTsState.value()
//判断当前事件 是create 还是pay
if(value.enentType == "create"){
//1.1如果已经支付过 正常支付 输出匹配成功结果 清空所有状态和定时器
if(isPay){out.collect(OrderResult(value.orderId,"pay-sussess"))
isCreateState.clear()
isPayedState.clear()
ctx.timerService().deleteEventTimeTimer(timeTs)
}else{
//1.2如果每来过 注册定时器 等待15分钟
val ts: Long = value.timestamp*1000L+900*1000L
ctx.timerService().registerEventTimeTimer(ts)
}
}
//2.如果是pay
else if(value.enentType == "pay"){
//判断是否来过create
if(isCreate){
//2.1如果create过 匹配成功 判断pay的时间和create的时间
if(value.timestamp*1000L
}
}