Apache Http Client พิมพ์ [อ่าน] ข้อผิดพลาด I / O: การอ่านหมดเวลา "

ฉันใช้ไคลเอนต์ apache http v4.5 และใช้เป็นไคลเอนต์ REST ในบางกรณี ฉันตรวจพบข้อผิดพลาด "[อ่าน] ข้อผิดพลาด I/O: หมดเวลาอ่าน" ซึ่งมาจากเฟรมเวิร์ก httpclient เมื่ออ่านเนื้อหาที่ได้รับและแสดงเป็นข้อความสุดท้าย

ดูเหมือนว่าจะไม่มีผลกระทบ แต่ฉันสงสัยว่ามีใครพอทราบหรือไม่ว่ามันมาจากไหนและจะแก้ไขได้อย่างไร ตามหัวข้อต่อไปนี้ (ลิงก์) ดูเหมือนว่า เป็นปัญหากับการกำหนดค่า "mutlithreaded"

อย่างไรก็ตาม ฉันใช้เฉพาะการกำหนดค่าเริ่มต้นของไคลเอ็นต์ http และในขณะที่ฉันใช้เวอร์ชัน v4 ฉันไม่รู้ว่าจะตั้งค่า "มัลติเธรด" เป็นเท็จได้อย่างไรเพื่อดูว่าจะสร้างความแตกต่างหรือไม่

ฉันพยายามตั้งค่าการหมดเวลาด้วย แต่ก็ไม่ได้ช่วยอะไร

มีคำแนะนำอะไรบ้าง?

บันทึก:

15:48:05.984 [main] DEBUG org.apache.http.wire - http-outgoing-8 << "HTTP/1.1 200 OK[\r][\n]"
15:48:05.984 [main] DEBUG org.apache.http.wire - http-outgoing-8 << "Date: Tue, 29 Dec 2015 14:48:03 GMT[\r][\n]"
15:48:05.984 [main] DEBUG org.apache.http.wire - http-outgoing-8 << "Server: Apache/2.4.12 (Win32) OpenSSL/1.0.1l PHP/5.6.8[\r][\n]"
15:48:05.984 [main] DEBUG org.apache.http.wire - http-outgoing-8 << "X-Powered-By: PHP/5.6.8[\r][\n]"
15:48:05.985 [main] DEBUG org.apache.http.wire - http-outgoing-8 << "Cache-Control: nocache, private[\r][\n]"
15:48:05.985 [main] DEBUG org.apache.http.wire - http-outgoing-8 << "Content-Length: 99[\r][\n]"
15:48:05.985 [main] DEBUG org.apache.http.wire - http-outgoing-8 << "Keep-Alive: timeout=5, max=99[\r][\n]"
15:48:05.985 [main] DEBUG org.apache.http.wire - http-outgoing-8 << "Connection: Keep-Alive[\r][\n]"
15:48:05.985 [main] DEBUG org.apache.http.wire - http-outgoing-8 << "Content-Type: application/json[\r][\n]"
15:48:05.985 [main] DEBUG org.apache.http.wire - http-outgoing-8 << "[\r][\n]"
15:48:05.985 [main] DEBUG org.apache.http.wire - http-outgoing-8 << "{"success":true,"data":{"id":1946,"location":"http:\/\/localhost:9001\/shop\/api\/articles\/1946"}}"
15:48:06.016 [main] DEBUG org.apache.http.wire - http-outgoing-8 << "[read] I/O error: Read timed out"

การเริ่มต้นไคลเอ็นต์ Http ของฉัน

HttpClientBuilder httpBuilder = HttpClientBuilder.create();

//      set timeout did not helped
//      RequestConfig.Builder requestBuilder = RequestConfig.custom();
//      requestBuilder = requestBuilder.setConnectTimeout(timeout);
//      requestBuilder = requestBuilder.setConnectionRequestTimeout(timeout);
//      requestBuilder = requestBuilder.setSocketTimeout(timeout);
//      httpBuilder.setDefaultRequestConfig(requestBuilder.build());

HttpClient httpClient = httpBuilder.build();

person megloff    schedule 29.12.2015    source แหล่งที่มา
comment
มันไม่พิมพ์อะไรเลย รหัสของคุณ จะพิมพ์ออกมา ไม่ชัดเจนว่าคุณกำลังถามอะไร   -  person user207421    schedule 04.02.2017
comment
คุณใช้ไคลเอนต์ apache http เวอร์ชันใดอยู่ ฉันกำลังถามว่ามีใครรู้บ้างไหมว่าทำไมข้อความแสดงข้อผิดพลาด [อ่าน] ข้อผิดพลาด I/O: หมดเวลาการอ่านปรากฏขึ้น   -  person megloff    schedule 05.02.2017
comment
ฉันก็เห็นสิ่งนี้เหมือนกัน นอกจากนี้ ยังเป็นที่น่าสังเกตว่าไม่มีข้อยกเว้นเกิดขึ้น และไม่ได้บันทึกเป็นข้อผิดพลาด เช่นเดียวกับ DEBUG   -  person BrianC    schedule 06.03.2017
comment
ดูเหมือนว่าจะเกี่ยวข้องกับการรวมการเชื่อมต่อด้วยการใช้ HttpClient แบบมัลติเธรด แต่จริงๆ แล้วไม่ได้ทำให้เกิดปัญหา   -  person BrianC    schedule 06.03.2017


คำตอบ (3)


ฉันใช้ httpclient 4.5.2 และในกรณีของฉัน การตั้งค่าการหมดเวลาตามคำขอช่วยได้:

HttpPost postRequest = new HttpPost("https://...");
postRequest.setHeader(..., ...);

RequestConfig requestConfig = RequestConfig.custom()
                        .setSocketTimeout(1000)
                        .setConnectTimeout(1000)
                        .build();

postRequest.setConfig(requestConfig);
person Ivan Hristov    schedule 09.08.2016

สาเหตุหนึ่งที่ทำให้เกิดข้อผิดพลาดดังกล่าวอาจเป็นเพราะเซิร์ฟเวอร์ปฏิบัติตามนโยบายการปิดการเชื่อมต่อ HTTP เมื่อมีการตอบกลับ หากเป็นกรณีนี้ ข้อผิดพลาดนี้อาจหลีกเลี่ยงได้โดยการปิดใช้งานการเชื่อมต่อซ้ำโดยไคลเอ็นต์ ดังนั้นจึงไม่จำเป็นต้องให้ลูกค้าตรวจสอบว่าการเชื่อมต่อยังคงมีอยู่:

httpBuilder.setConnectionReuseStrategy( (response, context) -> false );
person Sergey Ushakov    schedule 22.06.2017
comment
คุณยังสามารถใช้ new org.apache.http.impl.NoConnectionReuseStrategy() แทนการสร้างแลมบ์ดาของคุณเอง (แม้ว่าจะเล็กน้อยก็ตาม) - person Spork; 10.09.2018

เหตุผลไม่ใช่ "มัลติเธรด" แต่เป็น "พูลไคลเอ็นต์ http"

ไม่ใช่ข้อผิดพลาด เพียงทดสอบซ็อกเก็ตที่เก่า และจะดีเมื่อคุณต้องการนำซ็อกเก็ตกลับมาใช้ใหม่ ดู 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);
}
}

ตั้งค่าการหมดเวลาของซ็อกเก็ตเป็น 1 ms และอ่านสตรีมอินพุต ส่งคืนผลลัพธ์เหล่านี้:

  1. -1 สร้างการเชื่อมต่อใหม่
  2. ">0" การเชื่อมต่อที่ใช้ซ้ำ
  3. ข้อยกเว้นการหมดเวลา ใช้การเชื่อมต่อซ้ำ
  4. ข้อยกเว้น IO สร้างการเชื่อมต่อใหม่

เพื่อหลีกเลี่ยงข้อความนี้ เพียงตั้งค่าที่เหมาะสมสำหรับ validateAfterInactivity ซึ่งเป็นค่าขั้นต่ำของการหมดเวลาซ็อกเก็ตไคลเอ็นต์ เวลา Keep-alive (ส่งคืนโดย ConnectionKeepAliveStrategy) การหมดเวลาการเชื่อมต่อเซิร์ฟเวอร์ และเวลาหน่วงสำหรับ idleConnectionMonitor การดำเนินการนี้ไม่ได้ตรวจสอบสถานะการเชื่อมต่อ หากการเชื่อมต่อถูกรีเซ็ต การเชื่อมต่อใหม่จะถูกสร้างขึ้น

person avatas    schedule 08.03.2019