相信每个技术人员都不会甘心做“需求复印机”。
    不做需求复印机,有两种简单的方式。一种是在代码/模块/系统的结构上下功夫,例如前面几篇设计方案(审批、分发等)。另一种则是直接对业务流程开刀,例如这篇文章要举的例子。

背景

    大家一定都遇到过“批处理”这类需求。这次的背景就是一个批处理需求。按产品提出的需求,系统流程是这样的: 不做需求复印机——批量操作流程设计_第1张图片
    如果将这个流程直接“复印”到系统、代码中,显而易见会有性能风险。

思路

    这个需求的业务逻辑并不复杂,设计的关注点在于“性能”。性能风险的根源,看起来在于“一次提交N条数据”,实际上在于“同步请求”。因为同步请求会阻塞线程、占用资源,因此它对性能要求比较高。如果不是同步请求,而是异步响应,响应慢点儿其实也无所谓,性能风险自然消弭于无形。因此,我的方案就是用异步回调的方式来完成这个批处理请求。
    最简单的异步回调流程,就如下图所示。客户端向服务端批量地提交请求;服务端将异步任务提交给调度器后,立刻向客户端返回;然后异步任务再逐个地回调客户端接口,以告知真正的处理结果。
     不做需求复印机——批量操作流程设计_第2张图片

    这个简单流程已经足以说明异步回调的思路,其中的问题也显而易见。例如,这个方案中没有对异步任务做持久化、判重、重试、限流的处理。这可能导致任务丢失、调度错误等问题,也可能导致客户端被回调请求压死。
    因此,这个简单的异步回调流程中被加入了MQ,即利用消息服务来做异步任务的调度器,并借以解决持久化、重试、限流等问题。如下图所示:
    不做需求复印机——批量操作流程设计_第3张图片
    

类图与代码

    这个方案的设计关键点并不是类结构,而是业务流程。因此,与其它方案的类图、哪怕只是与上面的流程图相比,这次的类图都朴素得多。所以,这次我就偷懒不上类图和代码了。

后记

    这个方案其实并不出彩,它的起源只是我不想把产品需求“复印”到代码中而已。但是本质上,它也是一种技术驱动的思路:改变“怎么做”。尽管这个方案还没能进一步地改变“做什么”,但是,改变已从这里开始。