protected void connectSocket()

in src/main/java/com/uber/rss/clients/ClientBase.java [142:205]


    protected void connectSocket() {
        long startTime = System.currentTimeMillis();
        int triedTimes = 0;
        try {
            // we see java.net.UnknownHostException sometimes due to DNS issue, thus retry on this exception
            Throwable lastException = null;
            while (System.currentTimeMillis() - startTime <= timeoutMillis) {
                ClientConnectMetrics metrics = metricGroupContainer.getMetricGroup(getClientConnectMetricsKey());
                if (triedTimes >= 1) {
                    logger.info(String.format("Retrying connect to %s:%s, total retrying times: %s, elapsed milliseconds: %s", host, port, triedTimes, System.currentTimeMillis() - startTime));
                    metrics.getSocketConnectRetries().update(triedTimes);
                }
                triedTimes++;
                Stopwatch clientConnectLatencyTimerStopwatch = metrics.getSocketConnectLatency().start();
                try {
                    socket = new Socket();
                    socket.setSoTimeout(timeoutMillis);
                    socket.setTcpNoDelay(true);
                    socket.connect(new InetSocketAddress(host, port), timeoutMillis);
                    break;
                } catch (UnknownHostException | NoRouteToHostException | ConnectException socketException) {
                    if (socketException instanceof ConnectException && !ExceptionUtils.isTimeoutException(socketException)) {
                        // not timeout exception, e.g. may be connection refused, no need to retry and throw out exception
                        throw socketException;
                    }
                    M3Stats.addException(socketException, this.getClass().getSimpleName());
                    socket = null;
                    lastException = socketException;
                    logger.info(String.format("Failed to connect to %s:%s, %s", host, port, ExceptionUtils.getSimpleMessage(socketException)));

                    long elapsedTime = System.currentTimeMillis() - startTime;
                    if (elapsedTime < timeoutMillis) {
                        ThreadUtils.sleep(Math.min(timeoutMillis - elapsedTime, ThreadUtils.SHORT_WAIT_TIME));
                    }
                } finally {
                    clientConnectLatencyTimerStopwatch.stop();
                }
            }

            if (socket == null) {
                if (lastException != null) {
                    throw lastException;
                } else {
                    throw new IOException(String.format("Failed to connect to %s:%s", host, port));
                }
            }

            inputStream = socket.getInputStream();
            outputStream = socket.getOutputStream();

            connectionInfo = String.format("%s %s [%s -> %s (%s)]",
                    this.getClass().getSimpleName(),
                    internalClientId,
                    socket.getLocalSocketAddress(),
                    socket.getRemoteSocketAddress(),
                    host);
        } catch (Throwable e) {
            M3Stats.addException(e, this.getClass().getSimpleName());
            long elapsedTime = System.currentTimeMillis() - startTime;
            String msg = String.format("connectSocket failed after trying %s times for %s milliseconds (timeout set to %s): %s, %s", triedTimes, elapsedTime, timeoutMillis, connectionInfo, ExceptionUtils.getSimpleMessage(e));
            logger.warn(msg, e);
            throw new RssNetworkException(msg, e);
        }
    }