最近回顾
近期在开发一个新项目时,多个过程需要与第三方平台交互,由于其回调是众所周知的不可靠,在接收回调的同时,需要主动查询结果。那么理所当然的,定时器触发任务又成了必需。
其实在2018年包括之前时间,也有使用总结过自己认为的异步方式和如何使用redis来实现定时任务的并发锁。
先来谈谈日常中使用较多的定时任务方式。
- 如果是较为关键的业务,crontab专门设置一行用于PHP命令行运行或HTTP请求,目前我们主要以HTTP为主,这对多机器的负载均衡分配更好,且crontab的时间触发方式已经满足了要求,若想要实现秒级的任务触发,一个简单的sh程序即可;
- 另外crontab触发一段脚本执行逻辑,在此脚本文件内,以单线程方式陆续运行0-N个需要执行的任务;
- 以前也描述过,通过curl的CURLOPT_TIMEOUT配置项,以浪费1秒钟的代价实现某相关业务的伪异步。
简单列举以上三种方式,各有各的不好。
① 任务不多也倒还好,若存在5个、10个,甚至更多的任务需要定时触发,维护起来并不方便。
② 一个脚本单线程运行N个任务,太容易由于某个任务运行错误或运行时间超长导致后面的任务异常了。单就目前来观察,有的任务必须在凌晨4点前执行完毕,但是前面也有个时间要求度高的程序走着走着就超过了约定,这可不就歇了嘛,更不要说由于某个人的代码bug,导致抛错误被迫终止,一堆任务没排上队。另外又可能因为日志系统的疏落,不同功能日志夹杂在一块儿,出错定位极其不方便。
③ 必须“点对点”触发,用户的一个请求延伸出新请求来执行业务逻辑。这样问题也来了,如果不巧业务执行异常,或由于第三方等不可控系统的停摆,业务未执行完毕,那赶路一半没成功的请求可永远不会再来一遍的。更不幸的是,很多任务是需要延迟并且多次执行的,这总不能真while+sleep到底吧。又由于其“点对点”的特性,一个HTTP新增HTTP,占用了apache、nginx的连接数,无形中削弱了整个系统并发健壮能力。
这次的项目又重新引起了我的思