Spring Cloud Stream实战--异步任务的处理
本篇接上篇,用一个综合实例说明如何在在实际的项目中用MQ实现异步任务的处理。
一. 背景:
生成报告是一个比较耗时的操作, 根据报告的复杂程度,通常需要10几秒到几十秒的时间。如果使用同步请求,就会导致调用者一直等待,造成系统拥塞和用户体验不好的情况。因此将此任务从业务角度拆解成异步任务去实现:
1. 请求生成所需要报告的hashcode。
2. 通过hashcode获取所需要的报告。
二. 代码设计架构实现
设计架构的分解:
1. 请求生成所需要报告的hashcode,发送给MQ
2. MQ 收到消息,调用报告服务,生成报告,保存到数据库中
3. 调用者通过重试机制从本服务数据库中获取报告, 而不是从远程
4. 定时任务删除过期的报告
三. 代码实现
本实例的代码主要基于上篇MQ的基础之上,主要增加了数据库操作,重试机制以及定时任务删除操作。
整体结构图:

1. MQ:主要重新配置了一个新的exchange( 略)
2. 数据库操作 :使用JPA操作数据库(略)
3. Retryer: 重试机制去数据库里面检查报告是否生成:
public abstract class AbstractRetryer<T, P> { private final Integer maxRetry; private final int sleep; public AbstractRetryer(Integer maxRetry, Integer sleep) { this.maxRetry = (maxRetry!=null)? maxRetry : 5; this.sleep = (sleep!=null)? sleep: 0; } protected abstract T retry(P params); public T init(P parmas){ int tries = 0; while (tries < maxRetry){ log.info("Retrying {}",tries ); try { T value = retry(parmas); log.info("success retry {} times", tries); return value; } catch (Exception e){ tries++; log.error("Error retring to call {}", e); } sleep(); } return null; } private void sleep(){ if (sleep<=0){ return; } try { TimeUnit.SECONDS.sleep(sleep); } catch (InterruptedException e){ log.error("error", e); Thread.currentThread().interrupt(); } } }
4. Scheduler: 定时任务删除过期不用的报告;
public class ReportScheduler { @Value("${report.ttl}") private Integer ttl; private ReportRepository reportRepository; public ReportScheduler(ReportRepository reportRepository) { this.reportRepository = reportRepository; } @Scheduled(initialDelayString = "${report.initialDelay}", fixedDelayString = "${report.fixedDelay}") public void runTask(){ List<String> hashcodes = reportRepository.getDocumentBefore(ttl); hashcodes.forEach(code ->{ reportRepository.deleteById(code); log.info("delete the report {}", code); }); } }
学习,总结,沉淀,提高。

浙公网安备 33010602011771号