tomcat怎么平滑更新项目_Springboot项目平滑关闭及自动化关闭脚本

本文介绍了如何实现Springboot项目的平滑关闭,包括`GracefulShutdown`类的详细代码,以及如何定制关闭操作流程。同时,提供了自动化关闭脚本的使用步骤,涉及环境变量配置和文件格式转换。
摘要由CSDN通过智能技术生成

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 {

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 运行即可使用服务关闭脚本

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值