private void processNewResponses() throws InterruptedException, IOException {
    SocketServerResponse curr = (SocketServerResponse) channel.receiveResponse(id);
    while (curr != null) {
      curr.onDequeueFromResponseQueue();
      SocketServerRequest request = (SocketServerRequest) curr.getRequest();
      String connectionId = request.getConnectionId();
      try {
        if (curr.getPayload() == null) {
          // We should never need to send an empty response. If the payload is empty, we will assume error
          // and close the connection
          logger.trace("Socket server received no response and hence closing the connection");
          selector.close(connectionId);
        } else {
          logger.trace("Socket server received response to send, registering for write: {}", curr);
          NetworkSend networkSend = new NetworkSend(connectionId, curr.getPayload(), curr.getMetrics(), time, true);
          selector.send(networkSend);
        }
      } catch (IllegalStateException e) {
        metrics.processNewResponseErrorCount.inc();
        logger.debug("Error in processing new responses", e);
      } finally {
        curr = (SocketServerResponse) channel.receiveResponse(id);
      }
    }
  }
Thread that processes all requests from a single connection. There are N of these running in parallel
each of which has its own selectors
ambry-network/src/main/java/com/github/ambry/network/SocketServer.java