public void startup() throws InstantiationException {
    try {
      logger.info("[Startup] Starting VCR Server");
      ServerConfig serverConfig = new ServerConfig(properties);
      ServerSecurityServiceFactory serverSecurityServiceFactory =
          Utils.getObj(serverConfig.serverSecurityServiceFactory, properties, serverMetrics, registry);
      serverSecurityService = serverSecurityServiceFactory.getServerSecurityService();

      clusterMap = clusterAgentsFactory.getClusterMap();
      registry = clusterMap.getMetricRegistry();
      serverMetrics = new ServerMetrics(registry, VcrServer.class, VcrServer.class);
      nettyInternalMetrics = new NettyInternalMetrics(registry, new NettyConfig(properties));
      nettyInternalMetrics.start();

      long startTime = SystemTime.getInstance().milliseconds();
      registry = clusterMap.getMetricRegistry();
      reporter = reporterFactory != null ? reporterFactory.apply(registry) : JmxReporter.forRegistry(registry).build();
      reporter.start();

      AzureCloudConfig azureCloudConfig = new AzureCloudConfig(properties);
      NetworkConfig networkConfig = new NetworkConfig(properties);
      StoreConfig storeConfig = new StoreConfig(properties);
      CloudConfig cloudConfig = new CloudConfig(properties);
      ClusterMapConfig clusterMapConfig = new ClusterMapConfig(properties);
      SSLConfig sslConfig = new SSLConfig(properties);
      properties.verify();
      // These are required to be at these values going forward for backups.
      if (!azureCloudConfig.azureBlobContainerStrategy.equalsIgnoreCase(
          String.valueOf(AzureBlobLayoutStrategy.BlobContainerStrategy.PARTITION))) {
        throw new InstantiationException("azureBlobContainerStrategy must be PARTITION but is "
            + azureCloudConfig.azureBlobContainerStrategy);
      }
      if (azureCloudConfig.azureNameSchemeVersion != 1)  {
        throw new InstantiationException("azureNameSchemeVersion must be 1 but is "
            + azureCloudConfig.azureNameSchemeVersion);
      }
      if (!cloudConfig.ambryBackupVersion.equalsIgnoreCase(CloudConfig.AMBRY_BACKUP_VERSION_2)) {
        throw new InstantiationException("ambryBackupVersion must be 2.0 but is "
            + cloudConfig.ambryBackupVersion);
      }

      // TODO Make sure that config.updaterPollingIntervalMs value is large (~one day) for VCR.
      AccountServiceFactory accountServiceFactory =
          Utils.getObj(serverConfig.serverAccountServiceFactory, properties, registry);
      AccountService accountService = accountServiceFactory.getAccountService();

      StoreKeyFactory storeKeyFactory = Utils.getObj(storeConfig.storeKeyFactory, clusterMap);

      SSLFactory sslHttp2Factory = new NettySslHttp2Factory(sslConfig);
      NetworkClientFactory networkClientFactory;
      Time time = SystemTime.getInstance();
      if (clusterMapConfig.clusterMapEnableHttp2Replication) {
        Http2ClientMetrics http2ClientMetrics = new Http2ClientMetrics(registry);
        Http2ClientConfig http2ClientConfig = new Http2ClientConfig(properties);
        networkClientFactory =
            new Http2NetworkClientFactory(http2ClientMetrics, http2ClientConfig, sslHttp2Factory, time);
        logger.info("Using http2 for VCR replication.");
      } else {
        SSLFactory sslSocketFactory =
            clusterMapConfig.clusterMapSslEnabledDatacenters.length() > 0 ? SSLFactory.getNewInstance(sslConfig) : null;
        networkClientFactory =
            new SocketNetworkClientFactory(new NetworkMetrics(registry), networkConfig, sslSocketFactory, 20, 20, 50000,
                time);
        logger.info("Using socket channel for VCR replication.");
      }

      StoreKeyConverterFactory storeKeyConverterFactory =
          Utils.getObj(serverConfig.serverStoreKeyConverterFactory, properties, registry);
      VcrMetrics vcrMetrics = new VcrMetrics(registry);

      // This statement is only for legacy reasons otherwise post-merge jobs on dev-fabric break
      CloudDestinationFactory cloudDestinationFactory = Utils.getObj(cloudConfig.cloudDestinationFactoryClass,
          properties, registry, clusterMap, accountService);
      cloudDestination = cloudDestinationFactory.getCloudDestination();
      vcrClusterParticipant =
          ((VcrClusterAgentsFactory) Utils.getObj(cloudConfig.vcrClusterAgentsFactoryClass, cloudConfig,
              clusterMapConfig, clusterMap, accountService, storeConfig, cloudDestination,
              registry)).getVcrClusterParticipant();
      cloudStorageManager = new CloudStorageManager(properties, vcrMetrics, cloudDestination, clusterMap);
      scheduler = Utils.newScheduler(1, "vcr-scheduler-",true);
      vcrReplicationManager = new VcrReplicationManager(properties, cloudStorageManager, storeKeyFactory, clusterMap,
          vcrClusterParticipant, cloudDestination, scheduler, networkClientFactory, notificationSystem,
          storeKeyConverterFactory);
      vcrReplicationManager.start();
      logger.info("[Startup] Started VCR server in {}ms", SystemTime.getInstance().milliseconds() - startTime);
    } catch (Throwable e) {
      logger.error("[Startup] Failed to start VCR server due to {}", e.getMessage());
      e.printStackTrace();
      throw new InstantiationException();
    }
  }
Start the VCR Server.
@throws InstantiationException if an error was encountered during startup.
ambry-vcr/src/main/java/com/github/ambry/vcr/VcrServer.java