简介:
"优雅下线"是指在维护或更新一个在线服务时,以一种不中断正在进行的工作或服务的方式将其停止或下线。这种方式的目标是最小化对用户或客户的影响,使他们尽可能地感受不到服务的中断或停止。
通常,"优雅下线"包括以下几个关键方面:
- 平滑切换: 在进行服务维护或更新时,可以使用负载均衡或代理服务器等技术来确保新的服务实例已经准备好,并且在进行切换时无缝接管流量,而不会中断用户请求。这可以通过逐渐引导流量到新的服务实例来实现。
- 数据迁移: 如果您正在维护数据库或进行数据迁移,确保数据的迁移过程是平滑的,不会导致数据丢失或损坏。您可以考虑使用数据库复制、备份和还原等技术来实现。
- 兼容性保持: 在进行应用程序更新时,确保新版本与旧版本兼容,并且旧版本的客户端可以无缝地与新版本的服务进行通信。这可以通过版本控制和API设计来实现。
- 监控和回滚: 实施监控系统,以便在服务下线后能够及时发现问题并采取措施。如果出现问题,您可能需要快速回滚到之前的版本,以恢复正常的服务。
- 通知用户: 在服务维护期间,及时向用户提供通知,告知他们服务可能会短暂中断或受到影响。提前通知用户有助于减轻用户的不便,并提供替代方案(如果有的话)。
- 灰度发布: 在更新新功能或服务时,考虑采用灰度发布策略,逐渐将新功能引入部分用户,以便在全面发布之前进行测试和验证。
前提:
1、服务多实例,如果你的服务是单实例,那就没有什么必要了,服务最少保证两个实例
2、确保服务在运行期间采用了负载均衡策略,以便将流量分发到多个服务实例上
3、在下线之前,确保没有新的流量被发送到要下线的服务实例上。这可以通过负载均衡器的配置来实现
4、下线的方式保证安全性
思路:
Controller中写一个接口,用来获取当前服务的所有实例、判断实例个数、调用Eureka服务的下线Down接口,在部署前通过内网调用这个下线接口保证安全性
实现:
1、提供一个rest接口,/shutDown接口,通过服务注册中心DiscoveryClient获取当前服务的所有实例,循环判断实例数量是否大于1,大于则通过eureka的注册服务EurekaAutoServiceRegistration将当前实例进行下线,否则sleep3秒后再次判断实例数量是否大于1
@Slf4j
@RestController
@RequiredArgsConstructor
public class ShutDownController {
private final EurekaAutoServiceRegistration eurekaAutoServiceRegistration;
private final DiscoveryClient discoveryClient;
private final Registration registration;
@Value("${server.port}")
private Integer serverPort;
@RequestMapping(method = RequestMethod.GET, value = "/shutDown")
public String shutDown() throws InterruptedException {
// 保证当前服务必须含有实例才能下线
String serviceId = registration.getServiceId();
List<ServiceInstance> instancesList = discoveryClient.getInstances(serviceId);
boolean flag = true;
while (flag || instancesList.size() < 2) {
instancesList = discoveryClient.getInstances(serviceId);
for (ServiceInstance instance : instancesList) {
Map<String, String> metadata = instance.getMetadata();
String port = metadata.get("management.port");
if (StringUtils.isNotBlank(port) && serverPort.equals(Integer.parseInt(port))) {
flag = false;
} else {
flag = true;
break;
}
}
TimeUnit.SECONDS.sleep(3);
}
// 下线
eurekaAutoServiceRegistration.stop();
return "设置当前服务在eureka下线完成";
}
}
2、在docker部署时,调用服务下线的接口/shutDown让当前实例下线,然后sleep60s,让当前实例处理完已接收的请求
在部署的sheel脚本中进行以下配置,在docker stop之前将服务下线并休眠一分钟,然后再stop
# 服务下线
curl http://localhost:${appPort}/shutDown
# 等待服务处理完成
sleep 60
docker stop "${app_name}"
...