自动化场景业务的设计
自动化场景业务理解
最近接触到自动化场景,指设定好场景的触发条件以及执行目标指令,当条件通过成功时自动触发其业务。是一个比较复杂且细节繁多的设计,因为里面要考虑到非常多:并发、内循环、缓存压力、启动标识、结束标识、场景日志等等等等问题。所以结合本人当前的技术与业务水平,念叨叨一下
何为自动化
根据条件执行场景
用户通知系统:“我”要执行的目标 , 什么条件下才执行这个目标。
条件
自动化的条件大致分为三个:
- 时间:延时、当前
- 某个目标值的比较:大于、小于、大于等于、小于等于、等于、包含
- 前置动作判断:另一个动作的开始或结束、某个标识的变动、地球值或系统值变化[天气、CPU占用等...]
并且由于条件一个或多个 条件的判断上也会有如下三种:
- 一个满足
- 指定的某几个满足
- 全都满足
所以我们需要设计三个强大的条件引擎,满足条件判断的同时,外置一个处理器去判断所有条件的结果是否通过本次执行设置。
动作
动作大致分为两个:
- 执行一个业务、目标值
- 执行另一个场景
在自动化执行动作中,会涉及到一个非常非常难解决的问题,内循环执行问题。
产生条件:
- 场景套娃,场景A执行场景B,场景B执行场景C,场景C执行场景A
- 指令 — 条件套娃,场景A的执行指令,是场景B的执行条件;场景B的执行指令,是场景A的执行条件
由于条件与执行动作的多样性,并且每个条件、场景,的运行区域都不是在一个链路的线程上的。
所以导致即使是一个很简单的场景套娃:
如果在一个线程链路中,只要用一个Set存入每个场景的标识,在这个链路中每个场景执行前,判断一下Set中是否已存在当前场景标识,如果存在则结束链路
但执行引擎运行时,每个场景的运行区域都是互相隔离的,无法做到简单的通信。
技术难点
想这个业务场景的方案时,发现每想一个点,都会出现一个不好处理的问题。
这些问题或多或少,如果处理不当,都是造成整个程序,第三方组件数据库、缓存、微服务等的崩溃
时间段条件
如果场景的执行条件是,某周、某日的某个时间段
对于系统而言,必须创建一个每X秒去循环遍历 存在时间条件的场景 ,然后去判断:
- 符合,那么判断这个场景是否还有其他条件,如果没有则执行
- 不符合
所以我们要重点关注的是,每X秒 、 存在时间条件的场景 这两个问题
每X秒:
这个时间不能很频繁,也不能很长;
并且,一定一定不能设置在边缘时间范围:比如 1-5秒,55-59秒这样子。
不然对于用户体验是很糟糕的,因为常有用户需要进行自动化场景的测试,那么在当前时间的边缘时间时开启自动化场景。
当时由于遍历时间的问题,导致当前时间的这一分钟并不符合条件。
存在时间条件的场景
首先,一定纯做DB动作。
因为对于一个系统的稳定性来说,我们不能对这种未知大小的数据表进行一次次的DB操作。
所以我们必须定义一个合理的Key-zset值,比如:
将时间分为12段,每两小时一段作为一个key值,
当场景设置条件为时间时,则判断这个时间在哪个时间片中,将其场景对象存入对应的时间片缓存中。
延时执行
延时执行根据场景的设置有两种方式:
- 该场景延时场景
- 该场景中的某个指令,一个延时时间后,执行下一个动作
所以我们需要一个可靠的manager去管理场景发送 延时时间-动作
这里推荐直接使用 RabbitMq的延时插件:
https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases
然后根据以上两种方式,去控制发送的message,走不同的业务链路
内循环
首先造成内循环的原因上面提到过,主要有两种情况考虑:
- 指令-条件循环
- 场景循环
第一种解决方案想到过一个大概,但是仔细考虑又感觉会影响到用户使用体验
第二种解决方案很不靠谱。
但因想到,如果扼制住内循环的链路,肯定会影响到用户使用,因为:
如果用户不知道自己设置了内循环,但是需要这个场景执行,但由于内循环处理并不会执行。
第一种:
将每次场景执行往后的指令,通过
key:场景标识+指令标识+指令值+场景区域
存入缓存中
那么每个场景的条件判断前,先判断这个条件是否是 另一个场景的指令条件
key:场景标识+[指令对应条件]标识+条件值+场景区域
并且根据条件的判断类型:大于、小于、等于、大于小于.....
去判断该指令条件的值是否符合当前场景的条件
如果符合,则终止操作。
问题: 缓存的压力 ,难度【条件判断类型】,样式太多
第二种:
将执行过的场景标识存入缓存中,
key:场景标识
value:时间戳
当执行场景时,去缓存中判断,这个场景的最后时间戳时间,如果相隔近,则终止;
# 推荐:
内循环场景创建前,去提示用户,内循环问题
所以需要在创建场景前,通过遍历指令,与对应条件,
写一个深度DFS去check内循环合法性,并且通知用户是否创建
开启标识
什么时候开始这个场景的条件判断:
- 当条件值变动时
- 设置一个n秒循环
对于地球值、系统值的条件,我们只能创建一个n秒循环,然后去遍历有这个条件的场景,然后走条件引擎-》规则引擎链路
对于条件值变动的条件,则需要写一个能包容所有条件值判断的规则引擎
并发
一个场景开始判断条件->执行->执行解决,下发日志
是不可控时间的,所以当场景执行时,
对于用户来说,应该是可以修改的;
但是基于一个业务的原子性来说,我们是很不希望用户进行修改操作。
所以有考虑到几个方案去控制:
- 开始判断条件时,拷贝一份当前版本的场景镜像存入缓存
- 修改场景操作,与执行动作同步,只有当场景的执行动作整个链路完成,修改场景操作的事务才上交
- ...
缓存的访问、事务压力
在条件判断、执行、修改等等动作中,都会存在访问同一个key的情况
并且由于场景值的变动,第三方业务的影响等等;
需要做 取Key,修改Value,覆盖原Key的操作。
这样就会导致缓存的事务需要频繁的控制
很影响热点时段、热点条件符合时的场景访问缓存的需求
总结
是一个挺有意思的业务,时间有空的兄弟可以去试着开发一个自动化场景;
在未考虑细节前:内循环、并发、缓存、key值设置问题等等
但随着开发的进行,也就会发现细节中暴露出的各个问题。