@Override
  public void start() throws InstantiationException {
    long startupBeginTime = System.currentTimeMillis();
    try {
      logger.trace("Starting NettyServer deployment");
      if (Epoll.isAvailable()) {
        logger.trace("Using EpollEventLoopGroup in NettyServer.");
        bossGroup = new EpollEventLoopGroup(nettyConfig.nettyServerBossThreadCount);
        workerGroup = new EpollEventLoopGroup(nettyConfig.nettyServerWorkerThreadCount);
      } else {
        bossGroup = new NioEventLoopGroup(nettyConfig.nettyServerBossThreadCount);
        workerGroup = new NioEventLoopGroup(nettyConfig.nettyServerWorkerThreadCount);
      }
      for (Map.Entry<Integer, ChannelInitializer<SocketChannel>> entry : channelInitializers.entrySet()) {
        bindServer(entry.getKey(), entry.getValue(), bossGroup, workerGroup);
      }
      nettyMetrics.registerNettyPendingTasksGauge(bossGroup, "Boss");
      nettyMetrics.registerNettyPendingTasksGauge(workerGroup, "Worker");
    } catch (InterruptedException e) {
      logger.error("NettyServer start await was interrupted", e);
      nettyMetrics.nettyServerStartError.inc();
      throw new InstantiationException(
          "Netty server bind to port [" + nettyConfig.nettyServerPort + "] was interrupted");
    } finally {
      long startupTime = System.currentTimeMillis() - startupBeginTime;
      logger.info("NettyServer start took {} ms", startupTime);
      nettyMetrics.nettyServerStartTimeInMs.update(startupTime);
    }
  }
Creates a new instance of NettyServer.
@param nettyConfig the {@link NettyConfig} instance that defines the configuration parameters for the NettyServer.
@param nettyMetrics the {@link NettyMetrics} instance to use to record metrics.
@param channelInitializers a {@link Map} from port number to the {@link ChannelInitializer} used to initialize
                           a new channel on that port.
ambry-rest/src/main/java/com/github/ambry/rest/NettyServer.java