springboot + nginx 项目无感知发版

发布于:2024-05-31 ⋅ 阅读:(143) ⋅ 点赞:(0)

要点

  1. springboot项目

  2. spring-boot-starter-actuator插件

  3. 定制化tomcat关闭回调

  4. nginx 负载均衡(至少两台机器)

代码实现

1、引入pom

<dependencies>
    <!--集成springmvc框架并实现自动配置 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>


    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

2、定制化tomcat回调

CustomShutdown

/**
 * @author lixiaoyi
 * @description 定制shutdown 关闭逻辑
 *  1、 先暂停所有请求
 *  2、 等待现有线程处理完
 *  3、 关闭线程
 * @date 2021/7/22
 **/
@Slf4j
public class CustomShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {


    private static final int TIME_OUT = 30;


    private volatile Connector connector;


    @Override
    public void customize(Connector connector) {
        this.connector = connector;
    }


    @Override
    public void onApplicationEvent(ContextClosedEvent event) {


        /* 暂停所有请求 */
        this.connector.pause();


        /* 获取tomcat的线程池 */
        Executor executor = this.connector.getProtocolHandler().getExecutor();
        if (executor instanceof ThreadPoolExecutor) {
            try {
                ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
                /* 关闭线程 (等待线程处理完之后)*/
                threadPoolExecutor.shutdown();
                if (!threadPoolExecutor.awaitTermination(TIME_OUT, TimeUnit.SECONDS)) {
                    log.warn("当前应用等待超过最大时长{}秒,将强制关闭", TIME_OUT);
                    /* Try shutDown Now*/
                    threadPoolExecutor.shutdownNow();
                    if (!threadPoolExecutor.awaitTermination(TIME_OUT, TimeUnit.SECONDS)) {
                        log.error("强制关闭失败", TIME_OUT);
                    }
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }


    }
}

ShutdownConfig

@Configuration
public class ShutdownConfig {


    @Bean
    public CustomShutdown customShutdown() {
        return new CustomShutdown();
    }


    @Bean
    public ConfigurableServletWebServerFactory webServerFactory(final CustomShutdown customShutdown) {
        TomcatServletWebServerFactory tomcatServletWebServerFactory = new TomcatServletWebServerFactory();
        tomcatServletWebServerFactory.addConnectorCustomizers(customShutdown);
        return tomcatServletWebServerFactory;
    }
}

测试例子

@RestController
public class TestController {


    @RequestMapping("/test")
    public String test() throws InterruptedException {
        System.out.println("test");
        Thread.sleep(30000);
        String s = System.currentTimeMillis()+"";
        System.out.println("返回结果:"+s);
        return s;
    }


    @RequestMapping("/test1")
    public String test1() {
        System.out.println("test1");
        return "test1";
    }
}

3、nginx配置

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;


    #gzip  on;


    upstream backend {
       server localhost:8888;
       server localhost:8889;
      }


    server {
        listen       80;
        server_name  localhost;


        #charset koi8-r;


        #access_log  logs/host.access.log  main;


        location / {
             proxy_pass http://backend;
        }


        #error_page  404              /404.html;


        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }

}

操作流程

  1. 业务请求: http://localhost/test   30s 返回结果

  2. 注释 nginx 配置  server localhost:8888;

  3. 刷新nginx配置  nginx -s reload

  4. 关闭应用 http://localhost:8888/actuator/shutdown

  5. 重新启动关闭应用

  6. 启动完成 重复 2 3 4 5 步骤,第二步注释8889的机器 


网站公告

今日签到

点亮在社区的每一天
去签到