范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

还能这样玩?SpringBoot这些优雅停机的正确姿势你都会了吗?

  一、介绍
  什么叫优雅停机?
  简单的说,就是向应用进程发出停止指令之后,能保证正在执行的业务操作不受影响,直到操作运行完毕之后再停止服务。应用程序接收到停止指令之后,会进行如下操作:  1.停止接收新的访问请求  2.正在处理的请求,等待请求处理完毕;对于内部正在执行的其他任务,比如定时任务、mq 消费等等,也要等当前正在执行的任务执行完毕,并且不再启动新的任务  3.当应用准备关闭的时候,按需向外发出信号,告知其他应用服务准备接手,以保证服务高可用
  如果暴力的关闭应用程序,比如通过 kill -9  命令强制直接关闭应用程序进程,可能会导致正在执行的任务数据丢失或者错乱,也可能会导致任务所持有的全局资源等不到释放,比如当前任务持有 redis 的锁,并且没有设置过期时间,当任务突然被终止并且没有主动释放锁,会导致其他进程因无法获取锁而不能处理业务。
  那么如何在不影响正在执行的业务的情况下,将应用程序安全的进行关闭呢?
  二、方案实践
  SpringBoot 官方文档上,已经告诉开发者只需要实现特定接口即可监听到项目启动成功与关闭时的事件,相关接口如下:  CommandLineRunner 接口:当应用启动成功后但在开始接受流量之前,会回调此接口的实现类,也可以实现ApplicationRunner 接口,工作的方式与CommandLineRunner 与之类似 DisposableBean 接口:当应用正要被销毁前,会回调此接口的实现类,也可以使用@PreDestroy 注解,被标记的方法也会被调用
  基于此流程,我们可以创建一个服务监听类,用于监听到项目启动成功与关闭时的回调服务,示例代码如下:  @Component public class AppListener implements CommandLineRunner, DisposableBean {      @Override     public void run(String... args) throws Exception {         System.out.println("应用启动成功,预加载相关数据");     }      @Override     public void destroy() throws Exception {         System.out.println("应用正在关闭,清理相关数据");     }  }
  每一个 SpringApplication 在启用的时候,都会向 JVM 注册一个关闭钩子shutdown hook ,以确保ApplicationContext 在退出的时候,通过这个勾子通知 JVM,实现服务正常的关闭,以下介绍的所有关闭服务的方法,都是基于这一原理进行实现的。 2.1、方法一:通过Actuator的Endpoint机制关闭服务
  使用此方法,需要先添加 spring-boot-starter-actuator 监控服务依赖包,      org.springframework.boot     spring-boot-starter-actuator 
  默认配置下, shutdown 端点是关闭的,需要在application.properties 里配置里面开启: management.endpoint.shutdown.enabled=true
  虽然 Actuator 的端点,支持通过JMX 或HTTP 进行远程访问。而shutdown 默认配置下是不支持HTTP 进行Web 访问的,所以使用HTTP 请求进行关闭时的配置,也需要开启: management.endpoints.web.exposure.include=shutdown
  最后将 SpringBoot 服务启动之后,使用POST 请求类型,调用以下接口,即可实现关闭服务! http://127.0.0.1:8080/actuator/shutdown
  2.2、方法二:使用ApplicationContext的close方法关闭服务
  如果你不想添加 spring-boot-starter-actuator 监控服务依赖包来关停服务,也可以使用ApplicationContext 的close 方法来关停服务,他会自动销毁bean 对象并关停服务。
  只需要在应用启用的时候,获取 ApplicationContext 对象,然后在相关的位置调用close 方法,就可以关闭服务。
  示例代码如下:  @SpringBootApplication public class Application {      public static void main(String[] args) {       ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);        try {          TimeUnit.SECONDS.sleep(10);       } catch (InterruptedException e) {          e.printStackTrace();       }       //启动10秒以后,自动关闭       context.close();     } }
  当然我们也可以自己写一个 Controller ,获取对应的ApplicationContext 对象,通过api 操作调用close 方法关停服务,示例代码如下: @RestController public class ShutdownController implements ApplicationContextAware {      private ApplicationContext context;      @Override     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {         this.context = applicationContext;     }      /**      * 关闭服务      */     @GetMapping("/shutdown")     public void shutdownContext() {         ((ConfigurableApplicationContext) context).close();     } } 2.3、方法三:监听服务pid,通过kill方式关闭服务
  通过 api 方式来关停服务,在很多人看来并不安全,因为一旦接口泄漏了,意味着用户可以随便请求这个接口来关闭服务,其影响不言而喻,因此很多人建议在服务端,通过其他的方式来关闭服务,比如通过进程命令方式来关停。
  在 springboot 启动的时候将应用进程 ID 写入一个app.pid 文件,生成的路径可以指定,然后通过脚本命令方式来关闭服务。
  启动示例代码如下:  @SpringBootApplication public class Application {      public static void main(String[] args) {         SpringApplication application = new SpringApplication(Application.class);         application.addListeners(new ApplicationPidFileWriter("/home/app/project1/app.pid"));         application.run();     } }
  通过如下命令方式,可以安全的关闭服务。  cat /home/app/project1/app.pid | xargs kill
  这种方式,也是目前在 linux 操作系统中,使用较为普遍的一种解决方案,区别在于实现的方式可能不同,有的不用写文件,通过其他方式来获取应用进程 ID。
  如果使用 kill -9  的方式关闭服务,服务的监听器不会收到任何消息,类似于直接强杀应用进程,此方法不可取! 2.4、方法四:使用SpringApplication的exit方法关闭服务
  通过调用一个 SpringApplication.exit() 方法也可以安全的退出程序,同时会返回一个退出码,这个退出码可以传递给所有的context ,最后通过调用System.exit() 可以将这个错误码也传给JVM 。
  示例代码如下:  @SpringBootApplication public class Application {      public static void main(String[] args) {         ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);          try {             TimeUnit.SECONDS.sleep(5);         } catch (InterruptedException e) {             e.printStackTrace();         }         //5秒后,关闭服务         exitApplication(context);     }      public static void exitApplication(ConfigurableApplicationContext context) {      //获取退出码         int exitCode = SpringApplication.exit(context, (ExitCodeGenerator) () -> 0);         //退出码传递给jvm,安全退出程序         System.exit(exitCode);     }  } 三、其他监听介绍3.1、ApplicationListener
  如果有些服务,比如定时任务,我们想在 SpringBoot 关闭数据源连接池之前,将其关闭,可以通过实现ApplicationListener 接口,监听bean 对象的变化情况,在bean 对象销毁之前,执行相关的关闭任务。
  示例代码如下:  @Component public class JobTaskListener implements ApplicationListener {      @Override     public void onApplicationEvent(ApplicationEvent applicationEvent) {         // 在spring bean容器销毁之前执行的事件,防止数据库连接池在任务终止前销毁         if (applicationEvent instanceof ContextClosedEvent) {             System.out.println("关闭相关的定时任务");         }     } } 3.2、PreDestroy
  上文中,我们提到了实现 DisposableBean 接口,可以监听应用关闭前的回调处理,其实在自定义的方法上加@PreDestroy 注解,也可以实现相同的效果。
  示例代码如下:  @Component public class AppDestroyConfig {      @PreDestroy     public void PreDestroy(){         System.out.println("应用程序正在关闭…");     } } 四、小结
  本位主要围绕如何安全的关闭 SpringBoot 服务,进行了一些方案操作的介绍,如果有疏漏的地方,欢迎网友批评指出!
  原文:https://mp.weixin.qq.com/s/EasYsc9ixVVCPRvPTCCkYg
  如果感觉本文对你有帮助,点赞关注支持一下

蒸螃蟹,用冷水蒸还是开水蒸?都不对,教你一妙招,不断腿不流黄蒸螃蟹,用冷水蒸还是开水蒸?都不对,教你一妙招,不断腿不流黄马上就要到中秋节了,铁哥们送了我一张阳澄湖大闸蟹的提货卡,好家伙,这螃蟹真贵!4只4两公蟹和4只3两母蟹988元,还从来让西方失望了,1天内,中俄宣布3个重大合作事项,反霸权战斗打响美西方妄图通过各方面的经济制裁打压俄罗斯,同时遏制中国的强势发展,然而现实却让美西方失望了,1天内,中俄接连宣布3个重大合作事项,反击美元霸权战斗正式打响,中俄关系以及合作正在快速中国不想打,美铁了心要打,中方警告损人害己,美企股价连续暴跌中国已经不想与美国在高新科技领域博弈,但美国铁了心要对中国进行打压,这是为什么?中方警告美方停止这种损人不利己的行为,而美国企业股价连续暴跌已经很好地说明这一切。美国最近这几年疯狂迪卡侬中国副总裁赛万舟将持续在华投资中新网厦门9月10日电(记者杨伏山)中国是迪卡侬最重要的市场,没有之一,全球知名综合体育用品集团迪卡侬中国副总裁赛万舟(ServandoQuevedo)在厦门接受中新网记者采访时表云南省发改委严格落实减税降费政策稳步推进增值税留抵退税中国发展网讯据云南省发展改革委网站消息今年以来,云南省紧扣实体经济发展的难点堵点和卡点,统筹做好疫情防控和稳增长各项工作,将进一步加大退税减税降费力度摆在突出位置,有力有效应对经济2021年度云南省蚕桑产业发展报告来源云南省农业农村厅一云南省蚕桑产业发展现状(一)蚕桑生产情况蚕桑产业作为我省高原特色绿色友好产业之一,在脱贫攻坚促进农民增收区域特色经济发展中发挥着重要作用,十四五期间蚕桑产业将走进县城看发展丨云南腾冲边境小城的奋进路腾冲,地处云南西部边陲,与缅甸接壤,自古就是西南边陲重镇,有着厚重的历史文化底蕴和繁荣的商贸。如今,边境小城腾冲正发挥区位优势抓住开放机遇,努力建设文化旅游名城,推动兴边富民乡村振我是云南的,云南怒江的,是什么神仙地方我是云南的,云南怒江的,怒江泸水市,泸水市六库,六库傈僳族一段魔性Rap,引发全网跟风模仿,也让人们注意到世外桃源般的六库。六库历史悠久,有怒江第一镇之称。视觉中国六库原本是云南怒安徽宣城千年古镇枣香四溢村民们手持竹竿敲打满树的青枣。李晓红摄村民们在枣林里进行割枣比赛。李晓红摄中秋节临近,在安徽省宣城市宣州区水东镇碧山村,家家户户忙着制作蜜枣。李晓红摄中秋节临近,在安徽省宣城市宣州期待!桂林市将扩建这条二级公路为一级公路,直通大圩古镇大圩古镇是桂林市一个著名古镇,是广西古代四大圩镇之一,现在是桂林市一个著名的旅游景区,节假日有很多游客会到大圩古镇游玩。对于从桂林市出发的市民或者游客来说,去大圩古镇,一般走的路就个旧金湖,即将让你很惊叹金湖,是什么?除了湖水落霞垂柳晚风金湖还能给你什么?金湖商圈一个新名词将带给你更多关于生活的细节或许你曾经发现关于个旧生活的精彩与获得都在围绕金湖展开湖风吹过的空气偶尔也能带来饱足
京东如何抵御寒气?练内功,谋长远。撰文彦飞编辑王靖来源盒饭财经(IDdaxiongfan)收缩规模聚焦主业,把利润和现金流摆在更重要位置上,正成为国内科技公司的共识。近日任正非把寒气传递给每一个人的整车1000公里续航!这款车官宣率先搭载麒麟电池,宁德时代又火了?曾毓群最新发声今年6月23日,宁德时代第三代CTP技术麒麟电池正式发布。据悉,该电池系统集成度创全球新高,体积利用率突破72,能量密度可达255Whkg,可实现整车1000公里续航。该电池一经发李忠主持召开经济运行分析会8月26日,区委常委政府常务副区长李忠主持召开经济运行分析会,会议听取我区18月份经济运行情况,研究部署今后经济社会发展重点工作。区发改统计工科文体税务等部门负责人参会。李忠指出,新疆光伏风电项目我的看法我认为,新疆的光伏风电项目应引入个人投资者,自行购买退网板,自制风力发电机。光伏我觉得应该采取个人,公司和投资基金共荣计划,收购电价为每度0。2元,鼓励投资人上项目,国家电网提供免如何通过省提名项目移民加拿大省级提名计划(PNP)是技术职工移民到加拿大并获得永久居民身份的一种方式。该计划的目的是通过引入技术职工加强各省和地区的经济。省提名计划已经为历史上移民人口较少的省份,如大草原和大王强晋升上将9月8日,中央军委晋升上将军衔仪式在北京八一大楼举行。中央军委主席习近平向晋升上将军衔的北部战区司令员王强颁发命令状。新华社记者李刚摄中央军委晋升上将军衔仪式8日在北京八一大楼举行退税服务快优准市场主体保促稳山西省税务局退税减税六字诀助企纾困谋发展市场主体是经济活力的重要源泉。激发每个市场主体的活力,方能增强经济复苏的动力,稳住经济基本盘。今年以来,面对疫情影响和经济下行压力,为力保市场主体轻装上阵,持续焕发盎然生机,在省政七部门利好消息!氢燃料电池有望成新能源汽车新赛道(附股)什么是氢燃料电池?氢燃料电池是将氢气和氧气的化学能直接转换成电能的发电装置。其特点无污染无噪声高效率行业现状发展工信部等七部门印发信息通信行业绿色低碳发展行动计划(20222025企业想要资本运作,这篇文章把融资这事讲明白了互联网时代,商业活动异常复杂,发展速度超乎想象。无资本,不企业无论哪个行业的初创企业,都需要在资本的加持下,才能获得生存权和突破性成长。已经不能延续工业时代的传统思维,按部就班循规菜鸟位居全球首位!2022全球独角兽榜24家中国物流及科技企业上榜谁是2022年全球最抢眼的物流与供应链独角兽企业?8月30日,胡润研究院发布2022年中全球独角兽榜,全球独角兽企业中,中国以312家企业位居世界第二位。美国以625家(比去年猛增9月份后,个人账户的钱怎么用?市医保局给出解答近日,很多北京医保参保人员关心9月份后,个人账户的钱怎么用?北京市医保局给出相关解答。市医保局介绍,9月份后,个人账户的钱可以支付参保人员在定点医疗机构或定点零售药店发生的政策范围