代码之家  ›  专栏  ›  技术社区  ›  Flame_Phoenix

终止抢占实例的GCP负载平衡器行为

  •  0
  • Flame_Phoenix  · 技术社区  · 6 年前

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

    抢占式实例的问题

    any time

    让我们假设每个dispatcher VM不持有任何状态。它接收请求,对其进行处理,并向其他机器发出HTTP请求。

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

    问题:

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

    理论上,一个人应该有一个 shutdown script

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

    考虑

    将失败 因为一旦应用程序关闭,机器仍在运行,负载平衡器继续向机器发送请求,而不知道应用程序已经关闭。

    理想情况下,这些请求将作为失败的请求返回到负载平衡器,并将请求发送到另一台机器。然而,GCP负载平衡器不够聪明,无法做到这一点,因此它们没有。

    是哪一个?

    1 回复  |  直到 6 年前
        1
  •  2
  •   John Hanley    6 年前

    是否继续向终止的VM发送请求?

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

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

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

        2
  •  1
  •   Rohit Tandon    5 年前

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

    1. 负载平衡器每3秒钟检查一次实例的运行状况,在第三次运行状况检查失败后,将实例标记为不健康。因此,负载平衡器将在大约10秒钟内标记实例,并停止发送新请求。
    2. Java中的陷阱抢占信号 ContextCloseEvent (Spring boot) Runtime.getRuntime().addShutdownHook()
    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"); }
    推荐文章