Apache Http Client prints “[read] I/O error: Read timed out”"

前端 未结 3 853
隐瞒了意图╮
隐瞒了意图╮ 2021-01-02 06:49

I am using apache http client v4.5 and using it as a REST client. In some cases I recognize an error \"[read] I/O error: Read timed out\" which comes from the httpclient fra

3条回答
  •  伪装坚强ぢ
    2021-01-02 07:02

    The reason is not "multithread", but "http client Pool".

    It is not a error, just test the socket stale, and it is good when you want to reuse a socket. See org/apache/httpcomponents/httpcore/4.4.10/httpcore-4.4.10-sources.jar!/org/apache/http/pool/AbstractConnPool.java

    for (;;) {
        final E leasedEntry = getPoolEntryBlocking(route, state, timeout, tunit, this);
        if (validateAfterInactivity > 0)  {
            if (leasedEntry.getUpdated() + validateAfterInactivity <= System.currentTimeMillis()) {
                if (!validate(leasedEntry)) {
                    leasedEntry.close();
                    release(leasedEntry, false);
                    continue;
                }
            }
        }
        entryRef.set(leasedEntry);
        done.set(true);
        onLease(leasedEntry);
        if (callback != null) {
            callback.completed(leasedEntry);
        }
        return leasedEntry;
    }
    
    protected boolean validate(final CPoolEntry entry) {
        return !entry.getConnection().isStale();
    }
    
    public boolean isStale() {
        if (!isOpen()) {
            return true;
        }
        try {
            final int bytesRead = fillInputBuffer(1);
            return bytesRead < 0;
        } catch (final SocketTimeoutException ex) {
            return false;
        } catch (final IOException ex) {
            return true;
        }
    }
    

    org/apache/httpcomponents/httpcore/4.4.10/httpcore-4.4.10-sources.jar!/org/apache/http/impl/BHttpConnectionBase.java

    private int fillInputBuffer(final int timeout) throws IOException {
    final Socket socket = this.socketHolder.get();
    final int oldtimeout = socket.getSoTimeout();
    try {
        socket.setSoTimeout(timeout);
        return this.inbuffer.fillBuffer();
    } finally {
        socket.setSoTimeout(oldtimeout);
    }
    }
    

    Set socket timeout to 1 ms, and read input stream, return these results:

    1. -1 recreate new connection
    2. ">0" reuse connection
    3. timeout exception, reuse connection
    4. IO exception recreate new connection

    To avoid this message, just set proper value for validateAfterInactivity , it's the min value of client socket timeout, keep-alive time(return by ConnectionKeepAliveStrategy), server connection timeout, and the delay time for idleConnectionMonitor. This does not check connection state, if connect is reset, a new connection will be created.

提交回复
热议问题