storm是分布式的消息处理系统,spout任务发射出一条消息之后,可能要经过很多bolt任务的处理,而ack任务就负责跟踪每条消息的处理情况,直到所有的bolt都处理完毕。由于业务上的需要,不同类型的消息可能经过的bolt也不一样,不同的消息可能会做合并,那将各种复杂的场景抽象之后,spout、消息、以及bolt构成的是一张张有向图,如下图所示:
 

实时处理系统的自动化测试_第1张图片

spout是数据源头,也是有向图上的节点,bolt是有向图的节点,而M1,M2,M3是消息,它们沿着有向图经过各个bolt任务,处理或合并或分发,直到处理完毕,3条消息的ack value全部变成0. 有关ack的算法可参考https://github.com/nathanmarz/storm/wiki/Guaranteeing-message-processing

storm共有3种类型的task,spout,bolt,以及ack,它们分布在不同的机器不同的进程。对于spout任务,它是消息的来源,也是消息处理完成后ack任务汇报的对象。所以在自动化测试当中,应该实现这样一个通用的spout:它可以产生CASE指定的消息,并发送给CASE指定的bolt,另外,它还需要实现ack和fail回调,表示在消息处理完成或失败后自动化测试框架应该感知到。而对于spout任务,它是消息处理的地方,可能只是做些简单的处理,可能是跟其他的消息做join,可能是有向图的终点(表示处理完毕),也可能还要再转发出去,那么应该事先这样一个通用的bolt:它可以等待CASE指定的消息,并根据CASE的描述是转发、或是等待其他消息一起join后再转发、或是结束、或是等待其他消息一起join后再结束。

如果一个CASE就是一张有向图,那CASE的描述就可以采用有向图的描述方法,对于上面的那张有向图的描述如下:

spout_1(M1; emit; bolt1_1)
spout_2(M2; emit; bolt2_1)
spout_3(M3; emit; bolt3_1)
bolt1_1(M1; emit; bolt2_1)
bolt2_1(M1,M2; join and emit; bolt3_1)
bolt3_1(M1_M2,M3; join and emit; bolt4_1,bolt5_1)
bolt4_1(M1_M2_M3; emit; bolt6_1)
bolt5_1(M1_M2_M3; ack; null)
bolt6_1(M1_M2_M3; ack; null)

这样,qa人员只需要维护好各种有向图的描述,使用上述提到的通用的spout和bolt插件就可以做功能测试了。

因为目标bolt可能有多个task,而且有可能是位于不同的机器或进程上,所以目标bolt的任务id的选择可以是随机的,或者hash,这个自动化测试方案实现的时候还需要稍微做一些改进。