在长时间运行的Cloud PubSub订户服务中捕获侦听器异常

时间:2019-05-09 04:47:08

标签: google-cloud-platform google-cloud-pubsub

我正在尝试使用Java编写长期运行的订户服务。我已经设置了侦听器来侦听订阅服务器服务内的任何故障。我试图使这种容错能力,但我不太了解一些事情,以下是我的疑问/问题。

  1. 我遵循了https://github.com/googleapis/google-cloud-java/blob/master/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/SubscriberSnippets.java所示的基本设置。具体来说,我设置了addListener,如下所示。

如下面的代码所示,initializeSubscriber充当状态变量,该状态变量将确定订阅服务器服务是否应重新启动。在while循环内部,将连续监视此变量以确定是否需要重新启动。

我的问题是 1.如何在Subscriber.Listener的failed方法内引发异常,并将其捕获到主while循环中。我试图在失败的方法中抛出一个新的Exception(),然后将其捕获到catch块中,但是,我无法编译代码,因为它是一个已检查的异常。 2.如此处所示,我使用Java Executor线程运行监听器。如何处理侦听器失败?我可以在如下所示的常规Exception catch块下捕获侦听器故障吗?

try {
 boolean initializeSubscriber = true;
    while (true) {
        try {
           if (initializeSubscriber) { 
             createSingleThreadedSubscriber();
             addErrorListenerToSubscriber();
             subscriber.startAsync().awaitRunning();
             initializeSubscriber = false;
           }

          // Checks the status of subscriber service every minute
          Thread.sleep(60000);

        } catch (Exception ex) {
          LOGGER.error("Could not start the Subscriber service", ex);
          cleanupSubscriber();
          initializeSubscriber = true;
        }
    }
} catch (RuntimeException e) {

} finally {
    shutdown();
}
private void addErrorListenerToSubscriber() {
    subscriber.addListener(
      new Subscriber.Listener() {
          @Override
          public void failed(Subscriber.State from, Throwable failure) throws RuntimeException { 
            LOGGER.info("Subscriber reached a failed state due to " + failure.getMessage()
                + ",Restarting Subscriber service");
            initializeSubscriber = true; 
          }
      },
      Executors.newSingleThreadExecutor());
  }

  private void cleanupSubscriber() {

    try {
      if (subscriber != null) {
        subscriber.stopAsync().awaitTerminated();
      }
      if (!subscriptionListener.isShutdown()) {
        subscriptionListener.shutdown();
      }
    } catch (Exception ex) {
      LOGGER.error("Error in cleaning up Subscriber thread " + ex);
    }
  }

1 个答案:

答案 0 :(得分:1)

如果您只想在失败时重新创建订阅者,则不必向订阅者添加侦听器。您可以改为在awaitTerminated上捕获异常:

try {
  boolean initializeSubscriber = true;
  while (initializeSubscriber) {
    try { 
      createSingleThreadedSubscriber();
      subscriber.startAsync().awaitRunning();
      initializeSubscriber = false;
      subscriber.awaitTerminated();
    } catch (Exception ex) {
      LOGGER.error("Error in the Subscriber service", ex);
      cleanupSubscriber();
      initializeSubscriber = true;
    }
  }
}  catch (RuntimeException e) {
} finally {
  shutdown();
}

如果订户由于调用stopAsync而成功关闭,则awaitTerminated将不会引发异常。如果存在某种异常,则awaitTerminated将抛出IllegalStateException,因为状态将是FAILED而不是TERMINATED

请注意,瞬时错误由库本身处理。例如,如果服务器由于网络故障而暂时不可用,则库将无缝地重新连接并继续传递消息。导致订户状态改变的故障很可能是永久性故障,例如权限问题(运行订户的帐户无权订阅该订阅)或资源问题(例如该订阅已被删除)。在这些永久性失败的情况下,重新创建用户很可能会导致相同的错误,除非人们采取手动步骤进行干预并解决问题。