欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Springboot项目平滑关闭及自动化关闭脚本

程序员文章站 2024-02-22 10:56:10
springboot项目平滑关闭及自动化关闭脚本,供大家参考,具体内容如下 核心代码 gracefulshutdown.java shutdown.jav...

springboot项目平滑关闭及自动化关闭脚本,供大家参考,具体内容如下

核心代码

  • gracefulshutdown.java
  • shutdown.java
  • applicationstarterrunner.java
  • commoninfo.java
  • httpcommonutil.java
  • application.properties

操作步骤

核心代码

gracefulshutdown.java

package cnkj.site.utils;

import org.apache.catalina.lifecycleexception;
import org.apache.catalina.connector.connector;
import org.apache.catalina.util.lifecyclebase;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
import org.springframework.boot.web.embedded.tomcat.tomcatconnectorcustomizer;
import org.springframework.boot.web.embedded.tomcat.tomcatservletwebserverfactory;
import org.springframework.boot.web.servlet.server.configurableservletwebserverfactory;
import org.springframework.context.applicationlistener;
import org.springframework.context.annotation.bean;
import org.springframework.context.event.contextclosedevent;
import java.util.concurrent.executor;
import java.util.concurrent.threadpoolexecutor;
import java.util.concurrent.timeunit;

/*
 * @version 1.0 created by carol on 2019/4/25 16:22
 */
public class gracefulshutdown implements tomcatconnectorcustomizer, applicationlistener<contextclosedevent> {
 private static final logger logger = loggerfactory.getlogger(gracefulshutdown.class);

 private volatile connector connector;

 @override
 public void customize(connector connector) {
 this.connector = connector;
 }
 @override
 public void onapplicationevent(contextclosedevent event) {
 try {
  // 指定执行的方法
  shutdown();
  //手动清理内存
  system.gc();
  logger.warn("清理内存完毕,正在退出服务......");
  if (this.connector == null){
  return;
  }
  this.connector.pause();
  logger.warn("关闭全部连接......");
  executor executor = this.connector.getprotocolhandler().getexecutor();
  if (executor instanceof threadpoolexecutor) {
  try {
   threadpoolexecutor threadpoolexecutor = (threadpoolexecutor) executor;
   threadpoolexecutor.shutdown();
   logger.warn("当前服务线程池被关闭");
   if (!threadpoolexecutor.awaittermination(30, timeunit.seconds)) {
   logger.warn("tomcat thread pool did not shut down gracefully within 30 seconds. proceeding with forceful shutdown");
   }
  } catch (interruptedexception ex) {
   thread.currentthread().interrupt();
  }
  }
  this.connector.stop();
 } catch (lifecycleexception e) {
  e.printstacktrace();
 }
 }

 @bean
 public gracefulshutdown gracefulshutdown() {
 return new gracefulshutdown();
 }
 @bean
 public configurableservletwebserverfactory webserverfactory(final gracefulshutdown gracefulshutdown) {
 tomcatservletwebserverfactory factory = new tomcatservletwebserverfactory();
 factory.addconnectorcustomizers(gracefulshutdown);
 return factory;
 }


 /**
 * 执行服务关闭前的一些定制化操作
 * 通常需要确认以下步骤
 * 1.关闭kafka等数据连接
 * 2.flush内存中全部的未处理数据
 * 3.清理服务中全部待处理的数据
 */
 public void shutdown(){}
}

shutdown.java

import cnkj.site.utils.gracefulshutdown;
import org.springframework.stereotype.component;

/*
 * @version 1.0 created by carol on 2019/4/25 16:39
 */
@component
public class shutdown extends gracefulshutdown {

 @override
 public void shutdown() {
 // todo 定制化关闭操作流程
 // 关闭 kafka 消费
 // flush全部读写流
 // 清空队列
 // 关闭全部文件流读写
 }
}

applicationstarterrunner.java

package cn.migu.log.component;

import cnkj.site.utils.httpcommonutil;
import cnkj.site.commoninfo;
import org.springframework.boot.commandlinerunner;
import org.springframework.stereotype.component;

/*
 * @version 1.0 created by lxw on 2019/3/14 17:05
 */
@component
public class applicationstarterrunner implements commandlinerunner {

 @override
 public void run(string... args) throws exception {
 // 设置服务名
 commoninfo.setservice_name("service-name");
 // 自动设置服务启动后的进程号
 commoninfo.setservice_pid(httpcommonutil.getcurrentpid());
 }
}

commoninfo.java

package cnkj.site.utils;

import lombok.builder;
import lombok.data;
import org.springframework.boot.actuate.info.info;
import org.springframework.boot.actuate.info.infocontributor;
import org.springframework.stereotype.component;

import java.util.hashmap;
import java.util.map;


@data
@component
public class commoninfo implements infocontributor {

 //当前服务名
 private string service_name="service_name";
 //服务当前状态
 private int service_pid;


 @override
 public void contribute(info.builder builder) {
 builder.withdetail("service_name",service_name);
 builder.withdetail("service_pid", service_pid);
 }

 public void clearall(){
 this.service_name="";
 this.service_pid=-1;
 }

 public map getall(){
 map map = new hashmap();
 map.put("service_name", getservice_name());
 map.put("service_pid", getservice_pid());
 return map;
 }


}

httpcommonutil.java

package cnkj.site.utils;

import javax.servlet.http.httpservletrequest;
import java.lang.management.managementfactory;
import java.net.inetaddress;
import java.net.unknownhostexception;

/*
 * @version 1.0 created by carol on 2018/10/25 10:04
 */
public class httpcommonutil {

 /**
 * 获取当前服务的pid
 * @return pid
 */
 public static integer getcurrentpid(){
 string name = managementfactory.getruntimemxbean().getname();
 string pid = name.split("@")[0];
 return integer.valueof(pid);
 }
}

application.properties

#服务关闭
management.endpoint.shutdown.enabled=true
#监控相关
management.endpoint.prometheus.enabled=true
management.endpoints.web.exposure.include=info

操作步骤

项目使用步骤:

1.拷贝上面的 shutdown.java 代码到自己的项目中
2.在 shutdown.java 文件中的shutdown 方法中写定制化的关闭操作流程

脚本使用步骤:

1.从git获取最新的项目关闭脚本 地址
2.压缩server_close 为server_close.zip
3.上传 server_close.zip 到你服务所在服务器上的 /data/shell 路径下
4.配置环境变量 vim /etc/profile
5.在profile文件的最下面新增 export path=/data/shell/server_close:$path
6.保存并退出 :wq
7.如果提示 /bin/bash^m: bad interpreter: no such file or directory,请vim servicecontroll.sh,然后 :set fileformat=unix ,然后 :wq 保存并退出即可
8.cd /data/shell/server_close & ./servicecontroll.sh 运行即可使用服务关闭脚本

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。