技术栈是这样的:spring boot,openfeign,nacos,k8s
k8s部署 spring boot 两个项目(client和server,并且两个服务都注册到nacos上,client通过openfegin调用server)。
client 有2个deployment,一个service。server有10个deployment。
如果 滚动更新 server(10个deployment),虽然k8s能做到优雅终止。但是 nacos上注册的旧的server,好像没法确保已经被下线了。
要怎么做才能确保 nacos上的server下线。(可能要用到k8s的以下参数配置:terminationGracePeriodSeconds,Readiness , Liveness Probes,preStop)
在使用 Spring Boot、OpenFeign、Nacos 和 Kubernetes 的架构中,确保服务实例在滚动更新期间能够优雅地下线非常重要。以下是确保 Nacos 上的服务实例在滚动更新期间能够正确下线的步骤:
步骤 1: Spring Boot 应用程序配置
-
Spring Boot 应用程序:确保 Spring Boot 应用程序支持优雅关闭,并在关闭时从 Nacos 注册表中移除服务实例。
@Component public class GracefulShutdownHook implements ApplicationListener<ApplicationEvent> { private final NamingService namingService; private final String serviceName; public GracefulShutdownHook(NamingService namingService, String serviceName) { this.namingService = namingService; this.serviceName = serviceName; } @Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ContextClosedEvent) { // 在关闭时从 Nacos 注册表中移除服务实例 namingService.deregisterInstance(serviceName, "default", "127.0.0.1", 8080); } } }
-
Actuator 配置:确保 Spring Boot 应用程序启用了 Actuator,并且配置了安全相关的设置(如果需要的话)。
management.endpoints.web.exposure.include: shutdown management.security.enabled: false # 如果不需要安全设置
如果需要安全设置,可以配置基本认证:
management.security.enabled: true management.security.user.name: admin management.security.user.password: password
-
Nacos 配置:确保 Nacos 的客户端配置中包含了自动注销的配置,这样当服务实例关闭时,Nacos 会自动从服务注册表中移除该实例。
NacosProperties nacosProperties = new NacosProperties(); nacosProperties.setServerAddr("nacos-server-address"); nacosProperties.setNamespace("namespace-id"); nacosProperties.setEndpoint("endpoint"); nacosProperties.setPort(8848); nacosProperties.setUsername("username"); nacosProperties.setPassword("password"); // 设置客户端配置 ClientConfig clientConfig = new ClientConfig(); clientConfig.setServerAddr(nacosProperties.getServerAddr()); clientConfig.setNamespace(nacosProperties.getNamespace()); // 设置自动注销配置 clientConfig.setClientWorkerThreads(1); // 设置客户端线程池大小 clientConfig.setBeatInterval(5000); // 心跳间隔 clientConfig.setBeatTimeout(5000); // 心跳超时时间 clientConfig.setEndpoint(nacosProperties.getEndpoint()); clientConfig.setPort(nacosProperties.getPort()); // 创建 Nacos 客户端 NamingService naming = NacosFactory.createNamingService(clientConfig); // 注册服务 Instance instance = new Instance(); instance.setIp("your-ip"); instance.setPort(8080); naming.registerInstance("your-service-name", "your-group-name", instance);
步骤 2: Kubernetes 配置
-
设置 TerminationGracePeriodSeconds:在 Kubernetes 的 Deployment 配置中,为 Pod 设置
terminationGracePeriodSeconds
,这样 Kubernetes 会在销毁 Pod 前等待指定的时间,以便应用程序能够完成必要的清理工作。apiVersion: apps/v1 kind: Deployment metadata: name: my-server spec: replicas: 10 selector: matchLabels: app: my-server template: metadata: labels: app: my-server spec: terminationGracePeriodSeconds: 30 containers: - name: my-server image: my-server:latest ports: - containerPort: 8080 readinessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 5 periodSeconds: 5 livenessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 15 periodSeconds: 20 lifecycle: preStop: exec: command: ["sh", "-c", "curl -X POST http://localhost:8080/actuator/shutdown"]
-
配置 Health Checks:在 Deployment 中配置健康检查探针(Readiness 和 Liveness Probes),以确保 Pod 在启动后能够正确地响应请求,并在出现问题时能够及时重启 Pod。
readinessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 5 periodSeconds: 5 livenessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 15 periodSeconds: 20
-
使用 preStop 钩子:在 Deployment 的容器配置中,可以为容器配置
preStop
钩子。这可以通过在lifecycle
字段中定义preStop
来实现。lifecycle: preStop: exec: command: ["sh", "-c", "curl -X POST http://localhost:8080/actuator/shutdown"]
这个示例中,
preStop
钩子会在 Pod 终止之前发送一个 HTTP POST 请求到/actuator/shutdown
端点,以触发 Spring Boot 应用程序的优雅关闭。
总结
通过上述配置,你可以确保在 Kubernetes 环境下 Spring Boot 应用程序能够优雅地关闭,并在关闭前完成必要的清理工作。当 Kubernetes 执行滚动更新时,旧的 Pod 会在新的 Pod 启动之前优雅地下线,并从 Nacos 注册表中移除服务实例。这确保了服务的连续性和一致性。
需要注意的是,确保 Nacos 客户端配置正确,以便在 Pod 终止时能够从注册表中正确移除服务实例。同时,确保 Spring Boot 应用程序支持优雅关闭,并且在关闭时能够从 Nacos 注册表中移除服务实例。