@Override
  public void close() {
    shutDownOperationControllers();
    // wait for all the threads to actually exit
    waitForResponseHandlerThreadExit();
    // close the KeyManagementService
    if (kms != null) {
      try {
        kms.close();
      } catch (IOException e) {
        logger.error("Exception thrown on closing KMS", e);
      }
    }
    // close the crypto job handler
    if (cryptoJobHandler != null) {
      cryptoJobHandler.close();
    }
    for (Closeable resource : resourcesToClose) {
      try {
        resource.close();
      } catch (IOException e) {
        logger.error("Exception thrown on closing {}", resource.getClass().getName());
      }
    }
    if (repairRequestsDb != null) {
      try {
        repairRequestsDb.close();
      } catch (Exception e) {
        logger.error("Exception thrown on closing repair requests db", e);
      }
    }
    if (idConverter != null) {
      try {
        idConverter.close();
        idConverter = null;
      } catch (Exception e) {
        logger.error("Exception thrown on closing id converter", e);
      }
    }
    // close router metrics
    routerMetrics.close();
  }
Closes the router and releases any resources held by the router. If the router is already closed, then this
method has no effect.
<p/>
After a router is closed, any further attempt to invoke Router operations will cause a {@link RouterException} with
error code {@link RouterErrorCode#RouterClosed} to be returned as part of the {@link Future} and {@link Callback}
if any.
ambry-router/src/main/java/com/github/ambry/router/NonBlockingRouter.java