线程池使用不当导致系统假死
先说明一下任务详情 。
本来的任务是两个分开的接口,用户访问高峰期时会出现接口访问慢的现状
基于两个接口的功能是差不多的,并且为了减少用户的请求造成的网络IO的延时
---决定将两个接口合并
两个接口优化后在执行时分别时间大概是150ms左右
合并后接口时间在300ms左右
------------------------------------问题出现点:
我采用了异步编排技术实现了接口的合并,合并后的接口日常访问在170ms左右
当时的任务大概是这样的
当时只设置了一个线程池,参数分别为 20,250,ArrayBlock(100)
相信有经验的已经看出会产生什么问题了
先说结论,高峰期导致系统假死,访问量下去的时候系统恢复正常
双节点系统,配置较低
事故造成的原因:
第一步,线程参数设置不合理,不应该使用缓冲队列,直接使用无缓冲的队列
高峰期QPS在4000左右,任务瞬间打满,由于配置很低,所以大量的线程造成了cpu的切换,反而降低了任务的执行效率
第二步,原本一次请求一个线程可以完成的任务,一次请求创建了三个线程 ,并且两个子任务使用的是同一个线程池,造成了任务抢占线程的情况,试想,如果只有任务一抢到了线程,线程二就不会执行,主线程就会等待直到超时。
第三部,服务器自带重试,任务拒绝后,服务器自动重试,循环了第二步的问题,如果第二步问题不解决,就会造成 类似于第二步第三步的任务循环问题,只有少量的任务成功
总结:
异步编排要给不同的任务分配不同线程池
用户访问量大的接口不要使用多线程,会造成cpu创建更多的线程,内存升高,cpu切换频繁