private void bindServer(int port, ChannelInitializer<SocketChannel> channelInitializer, EventLoopGroup bossGroup,
      EventLoopGroup workerGroup) throws InterruptedException {
    ServerBootstrap b = new ServerBootstrap();
    Class<? extends ServerSocketChannel> channelClass =
        Epoll.isAvailable() ? EpollServerSocketChannel.class : NioServerSocketChannel.class;
    // Note: ServerSocketChannel option doesn't apply to SocketChannel
    b.group(bossGroup, workerGroup)
        .channel(channelClass)
        .option(ChannelOption.SO_BACKLOG, nettyConfig.nettyServerSoBacklog)
        .handler(new LoggingHandler(LogLevel.DEBUG))
        .childHandler(channelInitializer);
    b.bind(port).sync();
    logger.info("NettyServer now listening on port {}", port);
  }
Bootstrap a new server with a {@link ChannelInitializer} and bind it to a port.
@param port the port number to bind this server to.
@param channelInitializer the {@link ChannelInitializer} for request handling on this server.
@param bossGroup the pool of boss threads that this server uses.
@param workerGroup the pool of worker threads that this server uses.
@throws InterruptedException if binding to the port failed.
ambry-rest/src/main/java/com/github/ambry/rest/NettyServer.java