具有终止抢占实例的GCP负载均衡器行为

问题描述 投票:0回答:2

背景

我们有一个调度程序实例组,每个活动VM每秒接收大约700个请求。此调度程序位于自动扩展的负载均衡器后面。到目前为止,我们所有的VM都是regaular虚拟机,但是我们一直在研究使它们成为先发制人的可能性。

抢先实例的问题

根据文档,GCP可以在any time终止抢先实例。

假设每个调度程序VM都没有状态。它接收请求,处理它并向其他机器发出HTTP请求。

在任何给定时间,每个VM将同时处理大约700个请求,同时从负载均衡器接收数据。

如果处理700请求的抢占式VM收到要终止的信号,会发生什么?

好吧,理论上应该有一个shutdown script,确保处理这些请求完成然后杀死应用程序(干净退出)。这引出了一个大问题:

  • 但负载均衡器是否知道我的VM正在关闭?它会继续向终止VM发送请求吗?

注意事项

如果是,那么这意味着一些请求将失败,因为一旦应用程序关闭,机器仍然启动,负载均衡器继续向机器发送请求,而不知道应用程序已经关闭。

理想情况下,这些请求将作为失败的请求返回到负载均衡器,并将请求发送到另一台计算机。但是,GCP负载平衡器不够智能,所以他们不这样做。

如果负载均衡器知道这个VM被选择用于预留终止,那么就没有什么特别需要做的了。

哪一个?

google-cloud-platform google-compute-engine load-balancing preemptive
2个回答
1
投票

但负载均衡器是否知道我的VM正在关闭?它会继续向终止VM发送请求吗?

是的,负载均衡器将继续向实例发送请求。

您需要创建一个关闭脚本并从负载均衡器中删除您的实例。

并不是负载均衡器不够智能。负载均衡器不知道您的请求是否可以重试。该决定应由客户端/后端逻辑做出。

您的用例不是抢先实例的好例子。抢先实例将每24小时终止一次。如果您的目标是节省成本,请将长期实例定价的成本与优先定价进行比较。节省的费用不足以证明工程,测试和质量保证费用的合理性。

架构应该设计为失败,但我不会刻意选择一个会不断失败的架构。在你的情况下每24小时。您还有可能无法启动另一个实例来弥补增加的负载。并且存在所有实例将被终止的风险。


0
投票

我们有类似的问题。我们几乎通过负载均衡器运行状况检查解决了这个问题(在非常高的负载条件下存在一些问题)。 Trick现在在抢占信号的10-15秒内,负载均衡器会将实例标记为不健康,因为停止向该实例发送新请求。

解:

  1. 负载均衡器每隔3秒检查一次实例的运行状况,并在第三次运行状况检查失败后将实例标记为不健康。因此负载均衡器会在大约10秒内标记实例并停止发送新请求。
  2. 使用ContextCloseEvent (Spring boot)Runtime.getRuntime().addShutdownHook()在Java中捕获Preempt信号(在我的情况下,在JVM收到信号之前需要几秒钟)
  3. 设置运行状况检查失败,即运行状况检查端点将开始返回404。
  4. 在关机模块中休眠15-25秒,以便让新的请求完成
  5. 释放资源并执行关闭日志记录。 @EventListener public void onShutdown(ContextClosedEvent event) {
    log.warn("shutdown event received {}", event.getSource().toString());
    log.warn("/ping will respond 404, Main thread will sleep for 20 seconds to allow pending tasks to complete");
    
    isShuttingDown = true;
    try {
        Thread.sleep(SLEEP_BEFORE_SHUTDOWN_MILLIS);
    } catch (InterruptedException e) {
        log.error("sleep before shutdown interrupted", e);
    }
    
    log.warn("Shutting down now, daemon threads will continue work");
    releaseResources(); 
    
    log.info("{} {} on {} stopped.", NAME, VERSION, HOSTNAME);
    
    } //health endpoint @RequestMapping(value = "ping", produces = MediaType.TEXT_PLAIN_VALUE) public ResponseEntity ping() { if(isShuttingDown()) { log.warn("health failed - shutting down soon"); return new ResponseEntity(HttpStatus.NOT_FOUND); } return ResponseEntity.ok("pong"); }
© www.soinside.com 2019 - 2024. All rights reserved.