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

前端 未结 3 839
隐瞒了意图╮
隐瞒了意图╮ 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:00

    One of the reasons for having such an error may be that the server follows the policy of closing HTTP connections upon having responded. If that is the case, then this error may be avoided by disabling connection reuse by the client, so there would be no need for the client to verify that the connection is still alive:

    httpBuilder.setConnectionReuseStrategy( (response, context) -> false );
    
    0 讨论(0)
  • 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.

    0 讨论(0)
  • 2021-01-02 07:05

    I'm using httpclient 4.5.2 and in my case, setting the timeouts on a request helped:

    HttpPost postRequest = new HttpPost("https://...");
    postRequest.setHeader(..., ...);
    
    RequestConfig requestConfig = RequestConfig.custom()
                            .setSocketTimeout(1000)
                            .setConnectTimeout(1000)
                            .build();
    
    postRequest.setConfig(requestConfig);
    
    0 讨论(0)
提交回复
热议问题