Springboot + nacos + k8s 优雅停机

需要处理的问题

  1. 至少有一个服务可用
    K8S 配置滚动部署策略
  2. 服务下线后不再被调度
    • 服务关闭时主动下线 nacos
    • 服务关闭时清理应用里的 loadbalance 实例列表缓存
  3. 之前进来的请求可以返回
    延迟下线,最大可能保证功能结束

业务服务配置 nacos 优雅停机

优雅停机配置与最大等待时间

server:
  shutdown: graceful

spring:
  lifecycle:
    timeout-per-shutdown-phase: 40s
  cloud:
    loadbalancer:
      # 负载均衡缓存配置
      cache:
        enabled: true 
        ttl: 10s   

监听器代码

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.core.PriorityOrdered;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

@Component
@Slf4j
public class NacosShutdownEvent implements ApplicationListener<ContextClosedEvent>, PriorityOrdered {

    @Resource
    private NacosServiceManager nacosServiceManager;

    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

    @SneakyThrows
    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        // 获取服务实例
        NamingService namingService = nacosServiceManager.getNamingService();
        String service = nacosDiscoveryProperties.getService();
        List<Instance> instances = namingService.getAllInstances(service);
        String ip = nacosDiscoveryProperties.getIp();
        log.info("nacosDiscoveryPropertiesIP:{}", ip);
        for (Instance instance : instances) {
            String instanceIp = instance.getIp();
            log.info("instanceIp,{}", instanceIp);
            if (instanceIp.equals(nacosDiscoveryProperties.getIp())) {
                namingService.deregisterInstance(service, instance);
                log.info("deregisterInstance service,{},{}", service, ip);
            }
        }
        Thread.sleep(25 * 1000);
        log.info("end stop nacos");
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

网关

在网关配置过期时间

spring:
  cloud:
    loadbalancer:
      # 负载均衡缓存配置
      cache:
        enabled: true 
        ttl: 10s   

测试

使用jemeter 持续请求,观察在部署期间请求不报错
在这里插入图片描述

K8S

terminationGracePeriodSeconds:60s 这里的时间要大于springboot 里的睡眠时间

k8s 有停机前的处理步骤,可以在那里配置下线 + nacos 与睡眠等待,我采用的是springboot 监听器的方案,便于开发与观察。

其它

同样的方法,编写其他中间件,比如 kafka、xxl 的优雅停机逻辑,并且调整顺序,越小优先执行。

可以在关闭前打印当前活跃的 tomcat 容器中的线程数与队列,用于评估等待时间,待完善。

版本:
springboot 2.6.13
nacos 2.2.0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值