asynctask(踩坑日记六这一次栽在了 Async 上)

被浏览:8683

关注者:143

最佳回答:

上周六、日两天公司线下门店做了很多营销类的活动,周日下午的时候门店工作人员反馈几个营销页面打开异常,这边开发小伙伴赶紧去排查问题。现象是打开活动先出现黑屏,等待10-30秒才加载出来,中间并没有出现报错和加载失败情况。

p

针对这个现象和运维小伙伴依次检查排查了以下问题。

1、服务器内存使用

正常,都在正常范围内

p

2、调用地图次数限制

由于活动需要调用第三方地图API,担心会有限制,排查后是正常的。

3、数据库是否有等待进程没有释放

正常

4、防火墙流量

是平时的 5 倍左右。

5、页面JS加载时间

p

平均响应速度都在10秒以上。

服务器、网络、数据库和日志等均没有定义到具体问题所在,唯一的解释是流量突然增大导致并发性能低。小伙伴检查了 API 代码逻辑,发现都很简单可以支持很高的并发请求。

另外如果流量大应该会出现接口超时 time out、404等错误,在使用时并没有出现。

到目前还没定位到具体问题,那重启一下????

接着小伙伴们做出了重启的决定!

重启......................

响应速度突然变快了,但是经过 1-2 分钟后 又恢复到原先状态.................

到这里可以确定肯定是服务问题,接下来继续排查 API ,有小伙伴指出有可能方法上的 @Async 注解有问题。

经过检查发现 使用的是默认线程池......

p

成功!!!

由于代码比较古老,之前没有大力推广活动,平时流量没有超过临界点(或者用户感知比较若),导致这个坑一直存在。

如果使用Spring的 @Async 功能,必须要自定义线程池。如果不自定义异步方法的线程池那么系统默认使用的是SimpleAsyncTaskExecutor。SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。并发大的时候会产生非常严重的性能问题。

1、定义通用线程池

2、指定特定线程池

@Async默认使用Bean Name为executor的线程池。也可以根据Bean Name指定特定线程池

如果服务器资源充足,面向用户的应用尽量不用异步操作,除非是异步API的返回结果不被后续业务使用。例如:埋点日志 成功/失败都不影响正常业务逻辑。

获赞数:713

收藏数:34

回答时间:2024-04-07 21:26:26