背景

最近小伙伴解决了一个工单,描述为“手工推送案件无法推,提示token失效”,当前工单状态为待关闭,解决方案为“东软接口不稳定造成的,东软的接口恢复正常后,问题解决”,然后找现场让他们关闭工单,现场反馈:今天现场又出现相同的问题了!!!依然是token失效,工单关不了了。

过程

确认问题应用及版本

让对方把错误截图发了一下,发现好像不是卷宗自己的应用,跟卷宗团队小伙伴确认了一下,这是个定制的小工具。要到源码看了下,版本很干净,也不需要跟现场要版本号了,直接看当前代码即可。

问题初次定位

token失效有可能是服务器与客户端时差较大导致的,让现场核实了一下,就差几秒,不是这个原因。

让现场复现一下问题,并跟代码,发现所有请求东软接口的地方都需要在请求头传递token信息,而这个token是单例的,初次使用时会实例化。


现在既然找到token赋值的位置,且是单例的,现在又失效了,重启一下一定能解决,让现场重启


重启后确实解决了,从而得出结论“咱们只有在启动的时候申请了一次token,以后就再也没申请过,东软设置了token超时自动过期”,看看能不能让东软那边设置token永不过期

问题再次定位

但是!人家东软说token有效期是固定的两小时,且出问题的应用之前已经平稳运行好几天了。


基于目前的结论来看,每2个小时就需要重启一次应用才会避免token失效呀,现在的现象明显不是这样,怎么肥事?

继续找代码吧,看看都哪儿操作到token这个属性了,然后就找到了一个定时任务!


原来人家写了每半小时刷新一次token,而半个小时是小于东软的2小时的,所以理论上不会出现token失效的问题,那下一步的方向是哪儿呢?

定时任务嘛,看任务是否成功执行了就可以,反正他原来也有日志。

搜索了一遍之前的日志,没找到成功刷新的日志,这是怎么肥事?历史日志看不出来,咱们就看新日志吧。


到时间后为什么定时任务没执行?来,看代码,看日志!

代码里之前已经看到了,用的是spring提供的ThreadPoolTaskScheduler创建的定时器,没啥问题,看日志吧。


任务虽然执行成功了,但是日志有点儿怪呀,为什么刷新token的线程threadPoolTaskScheduler-1还被其他实例使用了?又不是主线程,他们应该是分别使用自己的才对呀,去SyncDataService看看。


哦哦,原来他们用的是同一个定时线程池的实例,扩散的看一下,原来有4个定时任务用的同一个实例。


那难道是他们在排队执行吗?去看一下ThreadPoolTaskScheduler的实现,网上说默认他只有一个工作线程,如果存在多个任务被触发时,会等第一个任务执行完毕才会执行下一个任务,看了下源码确实是这样。


回过头来看看日志是否可以佐证我们的猜想,11点41项目启动成功,定时任务实例化成功。


12点 SyncMaterials 任务开始执行(直接搜 threadPoolTaskScheduler-1 即可,因为默认线程大小是1,所以所有任务的工作线程名称都是他)


12点26 SyncMaterials 任务执行完毕,开始执行 SyncDataService


12点35 SyncDataService 任务执行完毕,开始执行 ScheduleService


再看看之前几天的日志,佐证一下猜想,可以看到确实是差不多每半小时执行一次。

解决方案

1、手工设置ThreadPoolTaskScheduler线程池大小,使其与定时任务数保持一致,每个任务用单独的工作线程,互不干扰(定时任务太多时其实存在资源浪费,每个任务都会有一个工作线程单独执行,间隔时间长且执行时间短的任务会始终占用着这个线程资源)

2、不要用spring自带的ThreadPoolTaskScheduler了,自己使用ScheduledExecutorService实现任务调度

3、找其他更合适的框架实现定时任务调度

结语

劲酒虽好,可不要贪杯哦!!!

脑子里为什么突然就有画面了???我还年轻,我一定不知道这些老年人才知道的广告词!!!

说正经的:不知道自己不知道->知道自己不知道->不知道自己知道->知道自己知道,咱们要努力做到最后面的那种境界。

套用到代码的世界就是,小白时期好多东西都不知道,定时任务都不知道是什么,只知道每天做自己已知的事儿,不就是增删改查嘛,有什么难的,大家都这样干,我也这样干;

后来听人家说了,有个定时任务的概念,spring可以实现这个功能,可以怎么用,自己遇到类似需求的时候,直接就去网上找关键字spring 定时任务,管他天高路远,管他山高水长,用就完了,干就是了;

再后来掉的坑多了,就知道看源码了,知道去看spring定时任务的原理了,后续工作中也知道再用spring定时任务的时候需要避免采什么坑,如何避免了,一阵沾沾自喜;

但后来被别人问的多了,或者自己开窍了,就知道除了spring自带了定时任务执行器,还有很多其他的方式可以实现相同的功能,他们各自的适用场景及优劣势是什么,自己当前的业务场景更适合用哪一种?开始做技术选型及预研了,这才是我们要追求的目标。

spring定时任务ThreadPoolTaskScheduler使用注意事项之线程池大小的更多相关文章

  1. 线程池大小设置,CPU的核心数、线程数的关系和区别,同步与堵塞完全是两码事

    线程池应该设置多少线程合适,怎么样估算出来.最近接触到一些相关资料,现作如下总结. 最开始接触线程池的时候,没有想到就仅仅是设置一个线程池的大小居然还有这么多的学问,汗颜啊. 首先,需要考虑到线程池所 ...

  2. 如何决定Web应用的线程池大小

    线程池(Thread Pool)在Web应用中线程池的大小决定了在任何一个时间点应用可以处理请求的并发数.如果一个系统收到的请求数超过了线程池的大小,那么超出的请求要么进入等待队列要么被拒绝.请注意, ...

  3. 如何计算tomcat线程池大小?

    背景 在我们的日常开发中都涉及到使用tomcat做为服务器,但是我们该设置多大的线程池呢?以及根据什么原则来设计这个线程池呢? 接下来,我将介绍本人是怎么设计以及计算的. 目标 确定tomcat服务器 ...

  4. 发一个可伸缩线程池大小的python线程池。已通过测试。

    发一个可伸缩线程池大小的线程池. 当任务不多时候,不开那么多线程,当任务多的时候开更多线程.当长时间没任务时候,将线程数量减小到一定数量. java的Threadpoolexcutor可以这样,py的 ...

  5. 如何决定 Web 应用的线程池大小

    在部署 web 应用到生产环境,或者在对 web 应用进行性能测试的时候,经常会有人问:如何决定 web 应用线程池大小?决定一个 IO 阻塞型 web 应用的线程池大小是一项很艰巨的任务.通常是通过 ...

  6. Java-如何合理的设置线程池大小

    想要合理配置线程池线程数的大小,需要分析任务的类型,任务类型不同,线程池大小配置也不同. 配置线程池的大小可根据以下几个维度进行分析来配置合理的线程数: 任务性质可分为:CPU密集型任务,IO密集型任 ...

  7. Spring配置Quartz任务调度、及 ThreadPool 线程池

    ONE.除了引入 Spring 相关的 jar 包,还要引入 Quartz 的 jar 包 <dependency> <groupId>org.springframework& ...

  8. ThreadPoolExecutor使用和思考(上)-线程池大小设置与BlockingQueue的三种实现区别

    工作中多处接触到了ThreadPoolExecutor.趁着现在还算空,学习总结一下. 前记: jdk官方文档(javadoc)是学习的最好,最权威的参考. 文章分上中下.上篇中主要介绍ThreadP ...

  9. 根据CPU核数合理设置线程池大小

    一般来说池中总线程数是核心池线程数量两倍,只要确保当核心池有线程停止时,核心池外能有线程进入核心池即可. 我们所需要关心的主要是核心池线程的数量该如何设置. 自定义线程池代码 package com. ...

随机推荐

  1. Python接口自动化测试实战-----附源码

    目录 1. 接口定义 2. 基本流程 3. 需求分析 4. 用例设计 5. 脚本开发 6. 结果分析 接口定义: 接口普遍有两种意思,一种是API(Application Program Interf ...

  2. js 手动实现 promise.all的功能

    在中高级面试中,实现一个promise.all是一个频率较高的面试题 首先分析下 promise.all(),(参考MDN) 接收一个promise的iterable类型(注:Array,Map,Se ...

  3. bzoj1972 SDOI2010-----猪国杀(模拟)

    题目自己去找吧 记得数据范围是<=10 注意事项: 1.牌库空的时候,要不断的抽第一张牌 2.反贼的决斗永远是向主公发的 3.每次判定无懈的时候,都是从使用锦囊的那个牌开始,记得敌意和殷勤的判断 ...

  4. C#开发BIMFACE系列47 IIS部署并加载离线数据包

    BIMFACE二次开发系列目录     [已更新最新开发文章,点击查看详细] 在前两篇博客<C#开发BIMFACE系列45 服务端API之创建离线数据包>与<C#开发BIMFACE系 ...

  5. Python中生成器的理解

    1.生成器的定义 在Python中一边循环一边计算的机制,称为生成器 2.为什么要有生成器 列表所有的数据都存在内存中,如果有海量的数据将非常耗内存 如:仅仅需要访问前面几个元素,那后面绝大多数元素占 ...

  6. 双系统升win11(grub启动问题修复与讲解)?!?

    起 最近win11不是出来了吗.(着急修复的可以直接跳到最后一步) 于是我就突发奇想给我半年没进去的windows升个级........ 于是我找到了我win11的升级包(从我一个同学哪儿) 工具都集 ...

  7. 原生js-返回顶部

    html部分: <body style="height:2000px"> <div id="div1"> 返回顶部 </div&g ...

  8. kivy 选择框

    from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.lang import builder # 注册 ...

  9. RogrePirates Scrum Meeting 博客汇总

    RogrePirates 博客目录 一.Scrum Meeting 1.Alpha阶段 第一次会议 第二次会议 第三次会议 第四次会议 第五次会议 第六次会议 第七次会议 第八次会议 第九次会议 第十 ...

  10. 算法:数字推盘游戏--重排九宫(8-puzzle)

    一.数字推盘游戏 数字推盘游戏(n-puzzle)是一种最早的滑块类游戏,常见的类型有十五数字推盘游戏和八数字推盘游戏等.也有以图画代替数字的推盘游戏.可能Noyes Palmer Chapman在1 ...