00:00
上节课我们对订单超时的这个需求做用CP实现了一下啊,那大家可能会发现在这个过程当中还是比较简单的,我们只要把模式定义出来,然后定义一下那个超时事件怎么去提取,怎么处理就可以了啊,当然有同学可能会想到说这个超时事件你难道不应该是直接把那个状态就更改掉吗?啊,我们也也提到,就是说这个状态其实我们只要做一个信息的提示,做一个检测就可以了,那后续的处理其实还是要交给这个业务逻辑,或者说你另外用其他的服务来处理这件事情,我们只要知道当前相当于我们就拿到一个报走信息就可以了,对吧?所以这就是我们现在要实现的这个需求,那除了cep的实现,可不可以用其他方式实现呢?哎,或者说大家思考一下cep底层到底是怎么去做的呢?怎么去处理不同状态之间的跳转呢?我们跟大家说CP的底层是用了一个。
01:00
啊,非确定性状态,状态机实现了一个状态机的这个表达,那如果我们用状态编程,大家可以去感受一下这个如果用状态编程怎么样实现这样的一个逻辑控制,所以接下来。在下边新建一个object,大家先想一想,我们这个这个需求大概怎么去实现啊,这个就叫allout without cp,这个需求我们怎么去实现啊?如果用状态编程的话,那这里边我们肯定要保存一些状态,对不对啊,然后去可能有定时器,可能有各种各样的控制逻辑,那大家想一想,在这个这种情况其实呃,应该是怎么处理呢?简单来看的话还好,就是只有两种情况,我们只考虑两种情况,一个是来了一个create。一个是来了一个配对吧,就是两种不同的数据类型,我们要考虑对不对,中间他们来其他情况不管,只要create后面有配,那就是正常匹配,如果要是create之后,那大家会想到得是不是得去定一个定时器啊。
02:15
对吧,如果说这个定时器到触发的时候,那个配还没来的话。那就应该超时做一个报警,对吧,这个订单timeout,所以直观的想的话,思路就是这样,那有些同学可能就会想到这个其实不是这么简单。因为我们在具体处理的过程当中还会遇到乱序的数据,那有可能什么呢?有可能是create先来,有可能是配先来,对吧?那如果要是配先来了,那算什么呢?啊,那有有同学可能就会想到,那如果配来的话,那就应该是已经支付了嘛,啊但其实配来了也有两种情况,那有可能create没来呢。Create create没来,那其实这种是另外一种异常,这不是超时,这应该是对,有可能我们出现了这个日志数据的丢失,或者是出现了一些异常情况才会出现,没有create,它直接就配了,对吧?啊这这可能我们也是需要检测出来去做报警的一些场景啊,这就跟我们业务流程设计,就是产品设计过程当中的一些流程相关了,呃,所以如果要考虑这个乱序,这个情况太多的话,这个太复杂啊,我们先做一个简版的实现,怎么样简版的实现呢?就是我们先不用输出那个。
03:34
正常匹配到create来了之后,有配的情况,我们就输出报警,超时报警的那种情况,那大家想一想,这个是不是比较简单啊。我们就可以设一个定时器,就是create,遇到create设一个定时器对不对,然后遇到P的时候,是不是可以改一个状态啊。甚至我们都可以不删那个定时器,我们可以干什么,直接设定一个状态,就表示有没有配来过。
04:05
如果有配来过。那是不是我到时候定时器触发的时候直接就说好,这是正常的对吧,如果没有配来过,那是不是就直接超时报警啊啊,所以这就是我们基本的一个最简单的实现思路。那大家看看这个代码里边怎么写吧。样衣类已经都定义好了,这里边就不写了,直接main函数,Main函数的话是不是前面都可以照抄,所以直接把这边前面是创建环境,然后读取这个订单数据,一直到K,呃,大家想是不是应该都差不多啊,对吧,这个过程其实大同小异啊。把这个引入之后改一下。好,另外这个时间语义引入,现在就把这个订单的数据都已经读进来了,接下来做什么操作呢?呃,接下来要做的操作也很简单,是不是直接定义。
05:06
一个process方式啊,对吧,Process方式处理。超时检,呃,就是进行超时检测。所以我们可以定义一个timeout warning输出,要输出warning信息。All the event stream对吧,那它在它的基础上是不是可以直接去写一个process啊,直接调一个process function,那这里边就要自定义了,All the time out。Warning,等下我们实现这个玩意儿就可以了,最后的输出timeout warning print,最后不要忘记还是要执行一下,这里我们用的是all the time without cp好。
06:16
实现自定义的处理函数。所以大家看,其实状态编程的话,这个流程倒比较简单对吧,前面就简单很多,直接点process,所有的东西都放在这里了,但是后边这个就稍微麻烦一点了,定义。Morning,他需要去实现一个什么东西呢?哎,我们现在是不是要对超时的事件做报警,这里边是要根据每一个订单ID来判断它后面有没有对应的那个配事件出现,所以已经做过k buy,我们这里要实现的是一个key的process方式。
07:02
里边的数据结构KIO,对吧?那K是什么呢?ID,那是long类型,输入是order event,输出是order result,对吧?这就是前面我们已经定义好的样例类。这里边必须要实现一个process element方法啊,来一个数据处理一个对吧?啊该怎么判断所有的逻辑都在里边实现,在这之前我们先定义状态对吧?这里边我们需要什么状态呢?首先啊,这里边我们就需要保存一个是不是配支付事件是否来过啊,是否来过的状态,所以这就相当于是一个标志位了,我们lazy定义一个is paid就叫is paid state,那它当然是一个value state。具体的类型是对布尔类型,这里面要引入一下state。
08:04
那么获取这个状态句柄的话,要用get runtime context get state,对吧,里边要去new一个value state。Script,然后里边给一个名字,这里叫is pay state,外边它的数据类型class。布尔,对吧,玻璃啊,所以这是我们要保存的一个状态,然后接下来就可以真正的在这个里边去写我们想要实现的逻辑了,这个逻辑里边首先干什么呢?啊,先把状态拿出来对不对,先取出状态。啊,标志位,所以定义一个easy pay的它就等于。状态点value把它取出来对吧,然后接下来是不是我们就要开始if else了,对吧?各种if else判断就可以了,我们判断是什么呢。
09:11
是不是其实就是事件的类型是create,事件的类型是配两种情况对吧?首先我们判断value even type,如果要是。Create的话啊,大家会想到我们是不是接下来是应该要注册那个定时器啊,但是如果考虑到有这个类似于乱序的一些操作的话,呃,是不是有可能之前配已经来过了。那配型来过是什么情况?配型来过是不是一配的这个状态位应该就是已经制成触了呀,默认是false,这里边是不是假如说他已经来过就会制成触,所以假如说我们这里边要去定义定时器的话,是不是应该他没有来过。所以这里边如果。
10:02
呃,遇到了create事件并且没有来过,那是不是就定义注册定时器啊,开始等待对不对?如果已经来过,当然就不用注册了啊。定时器开始等待,所以这里边我们要去定义一个定时器是不是c TX time server,然后even time timer,对吧?啊,这里大家注意我们定义的还是事件时间的定时器,因为我们前面关于这里边超时不超时的这个时间是不是都看的是本身用户数据产生时候的那个时间,而不是我们什么时候处理,对吧?那有可能,呃,那那边产生的很快,数据产生很快,我们这边还没处理过来,那如果你要是定义这个处理时间的话,显然就不合适了,所以这里边。
11:01
这个时间戳应该就是value.time注意时间戳是一个长整型,所以乘以1000,另外还要再加上对,加上15分钟,那是不是就是。啊,15其实大家知道是900对吧,15乘以60再乘以1000对吧?啊这样的一个毫秒数,把它注册好。在火后面再来一个瑞,那有什么问题吗?它下面后面再来个隔瑞的,那么这个定阻器的,它是报警,它什么时候报警的哦,当然这里边大家会发现我们要处理的这种情况也做了一个U,做了一个简化,就是我只考虑一个create一个配这种情况,对吧?那如果说create来了之后又create一次,呃,那那显然这个逻辑是不是处理不了啊,那相当于是要重复的去定义这个,呃,Create相关的这个呃定时器对不对?然后后面的那个配有可能只来一个配的话,可能就就会有问题了,对吧?啊所以这里边大家注意一下,这里我们默认的情况是一个create一个配这种情况啊,所以接下来那另外的情况还有什么呢?Value里边的type,对,如果要是配的话,是不是也得去处理一下啊?
12:22
如果是配的话怎么办?如果是配事件,那么就是不是要把状态更改一下啊对吧,直接把。状态改为。True。啊,大家看这就是一个比较简化的一个讨巧的方法,就是相当于实现了一个什么呢,就是不管怎么样,都是等到定时器触发的时候,再去判断到底有没有来过,对不对啊,所以这里边其实是这样的一种方式。
13:01
Update处有同学可能想到按道理你这里边已经来了的话,是不是可以可以直接输出,哎,就已经已经成功支付了,但是我们可能会考虑到,那假如说后边这个他先来了,那个那个就是create没来呢,对吧,出现这种乱序的情况,这个算什么呢?如果我们想处理这种各种各样复杂的情况的话,那可能就呃,你就不能那么简单直接输出,我们这里边就是把它直接统一全放在定时器触发的时候再去输出,那接下来这里边这个逻辑处理完了,是不是还得有一个定时器触发的处理过程啊。定时机出发的时候,我们要做什么操作呢?大家想一想是不是这个很简单,就是既然是定时器触发,那是不是一定有对应的那个create来过,然后触发的时候我是不是只要判断配来了没有就可以了,对吧?如果配没来,那是不是相当于超时,如果要是配来过是不是正常匹配啊,正常输出啊,当然就是说如果说这个定时器就就是Chris就没来的话,是不是相当于就没有定时器啊。
14:16
那相当于在这个过程是不是就一直会等这个create来了,才能检测出来对应的匹配,所所以相当于是这样的一个过程啊啊,那这里边我们就是直接判断呃,Is pay的状态对吧,是否为处。首先我们先把这个拿到啊,Is paid还是paid state value先拿到,那么如果大家会想到,如果它是。如果它是真的话,那么我们可能直接输出的是一个正常的数据,对不对?All the result,那这里边的ID从哪里去找呢?上下文,Process function里面有上下文对吧?是不是可以get current key,直接拿到当前的ID,然后后边给一条数据。
15:15
Order pay的successfully,那当然了,如果是else的话,没有来过这个配的话,那是不是相当于输出一个,当然大家可以把这个定义成测输出流啊,我们这里边是简,简化了就全是一个流,里边输出不同的信息,同样这里也是当前的k order ID,然后可以输出一个order timeout,对吧?哎,所以大家看这个过程非常的简单对不对啊,然后接下来再去做一个清空状态,那就是is paid state是不是要做一个clear操作啊好,我们就把。
16:02
这个简单的功能就已经实现完了啊,当然我们可以在这里边做一个运行一下做一个检测。好,我们来逐条输入,还是做一下测试。看一看它的这个效果是什么样的,首先四二这个输入对吧,然后四三。输入呃,330输入这个,然后二九输入。输入这个配支付这条数据,这这条订单,然后三零去配。诶,大家看现在怎么还没有输出啊。之前我们不是那个autom,只要掌握那个位置就可以输出一个,至少检测到那个二九是是正常的嘛,对吧,那怎么现在什么都没有输出啊对,因为我们的定义是不是必须要等到定时器触发的时候,15分钟之后才会去,呃,就是给出我们这个结论,到底是成功支付还是还是timeout对吧?啊,所以这里边我们就只能是等到15分钟之后再看了,我再创建一个五六。
17:18
然后15分钟,我们直接到跳到15分钟之后吧,时间跳过,比方说。呃,这个2022是不是15分钟之后了。好。诶,大家看这里边直接就输出了三条数据对吧。然后前面的二九跟三零,我们前面是不是都已经支付过了,而最后的那个五六没有支付,所以是order timeout,而且大家看这个是马上输入一条马上输出对不对啊,当然了,这个是因为触发了我们定时器嘛,当然是这样,所以这个过程当中大家会发现简单实现的话,其实呃,还是逻辑还是比较比较明确,比较简单的,但是这里面有很多问题。
18:03
有什么问题呢?首先我们是不是不能做到正常成功匹配的那些,是不是不能做到来一条马上直接输出啊,这跟capp里边的实现还是有还是有差距,对不对?呃,另外其实我们会想到在比较复杂的一些逻辑处理里边,可能还没有完整的处理好,对吧?因为我们想到,哎,可能这个比方说先来一个create和先来一个配,他们可能会有不同的这种处理过程。如果说我们要想再实时的把它输出的话,这个匹配好的这个结果实时输出的话,那大家想你是不是就必须得去针对不同的情况分别讨论了,先来create,再来配,这有可能来匹配成功success对吧,先来配再再来这个create是不是也有可能出现这是成功匹配的状态啊,乱序数据嘛啊,所以如果我们想做的更复杂,那就要把这个各种不同的情况展开去讨论了。
我来说两句