Eureka 的 TimedSupervisorTask 类(自动调节间隔的周期性任务)
欢迎访问我的 GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
起因
一个基于 Spring Cloud 框架的应用,如果注册到了 Eureka server,那么它就会定时更新服务列表,这个定时任务启动的代码在 com.netflix.discovery.DiscoveryClient 类的 initScheduledTasks 方法中,如下(来自工程 eureka-client,版本 1.7.0):
上述代码中,scheduler 是 ScheduledExecutorService 接口的实现,其 schedule 方法的官方文档如下所示:
上图红框显示:该方法创建的是一次性任务,但是在实际测试中,如果在 CacheRefreshThread 类的 run 方法中打个断点,就会发现该方法会被周期性调用;
因此问题就来了:方法 schedule(Callable<V> callable,long delay,TimeUnit unit)创建的明明是个一次性任务,但 CacheRefreshThread 被周期性执行了;
寻找答案
打开的 run 方法源码,请注意下面的中文注释:
真相就在上面的最后一行代码中:scheduler.schedule(this, delay.get(), TimeUnit.MILLISECONDS):执行完任务后,会再次调用 schedule 方法,在指定的时间之后执行一次相同的任务,这个间隔时间和最近一次任务是否超时有关,如果超时了就间隔时间就会变大;
小结:从整体上看,TimedSupervisorTask 是固定间隔的周期性任务,一旦遇到超时就会将下一个周期的间隔时间调大,如果连续超时,那么每次间隔时间都会增大一倍,一直到达外部参数设定的上限为止,一旦新任务不再超时,间隔时间又会自动恢复为初始值,另外还有 CAS 来控制多线程同步,简洁的代码,巧妙的设计,值得我们学习;
欢迎关注 InfoQ:程序员欣宸
版权声明: 本文为 InfoQ 作者【程序员欣宸】的原创文章。
原文链接:【http://xie.infoq.cn/article/eab370225cd5030f2c9266f1e】。文章转载请联系作者。
评论