Apache HttpClient 중간 오류 : NoHttpResponseException
XML로 POST 메서드를 수락하는 웹 서비스가 있습니다. 임의의 경우에 잘 작동하고 메시지와 함께 IOException을 던지는 서버와 통신하지 못합니다 The target server failed to respond
. 후속 호출은 정상적으로 작동합니다.
대부분 전화를 걸고 응용 프로그램을 10-15 분 동안 유휴 상태로 둘 때 발생합니다. 그 후 첫 번째 호출은이 오류를 반환합니다.
나는 몇 가지를 시도했습니다 ...
재시도 핸들러를 다음과 같이 설정했습니다.
HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler() {
public boolean retryRequest(IOException e, int retryCount, HttpContext httpCtx) {
if (retryCount >= 3){
Logger.warn(CALLER, "Maximum tries reached, exception would be thrown to outer block");
return false;
}
if (e instanceof org.apache.http.NoHttpResponseException){
Logger.warn(CALLER, "No response from server on "+retryCount+" call");
return true;
}
return false;
}
};
httpPost.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, retryHandler);
그러나이 재 시도는 호출되지 않았습니다. (예, 올바른 instanceof 절을 사용하고 있습니다). 이 클래스를 디버깅하는 동안 절대 호출되지 않습니다.
나는 심지어 설정을 시도 HttpProtocolParams.setUseExpectContinue(httpClient.getParams(), false);
했지만 사용하지 않았습니다. 누군가 내가 지금 할 수있는 것을 제안 할 수 있습니까?
중요 예외가 발생하는 이유를 파악하는 것 외에도 중요한 문제 중 하나는 재시도 처리기가 여기서 작동하지 않는 이유입니다.
연결 관리자에 의해 활성 상태로 유지되는 대부분의 영구 연결이 부실해집니다. 즉, 대상 서버는 연결이 유휴 상태 인 동안 HttpClient가 해당 이벤트에 반응하지 않고 끝에서 연결을 종료하여 연결을 반쯤 닫히거나 '부실'하게 만듭니다. 일반적으로 이것은 문제가되지 않습니다. HttpClient는 풀에서 임대시 연결 유효성을 확인하기 위해 여러 기술을 사용합니다. 부실 연결 검사가 비활성화되고 부실 연결이 요청 메시지를 전송하는 데 사용되는 경우에도 요청 실행은 일반적으로 SocketException이있는 쓰기 작업에서 실패하고 자동으로 다시 시도됩니다. 그러나 어떤 상황에서는 쓰기 작업이 예외없이 종료 될 수 있으며 후속 읽기 작업은 -1 (스트림 끝)을 반환합니다.
상황을 해결하는 가장 간단한 방법은 비활성 기간이 지난 후 풀에서 1 분 이상 유휴 상태였던 만료 된 연결 및 연결을 제거하는 것입니다. 자세한 내용 은 HttpClient 자습서의이 섹션을 참조하십시오 .
받아 들여진 대답은 맞지만 해결책이 없습니다. 이 오류를 방지하려면 이 답변 과 같이 HTTP 클라이언트에 대해 setHttpRequestRetryHandler (또는 Apache 구성 요소 4.4의 경우 setRetryHandler)를 추가 할 수 있습니다 .
HttpClient 4.4는 요청자에게 반환하기 전에 부실한 연결을 확인하는 것과 관련된이 영역의 버그로 어려움을 겪었습니다. 그것은 하지 않았다 연결이 부실 여부를 확인하고, 즉시이 다음 결과 NoHttpResponseException
.
이 문제는 HttpClient 4.4.1에서 해결되었습니다. 이 JIRA 및 릴리스 노트를 참조하십시오.
오늘날 대부분의 HTTP 연결은 달리 선언하지 않는 한 영구적 인 것으로 간주됩니다 . 그러나 서버 자원을 절약하기 위해 연결이 영원히 열려있는 경우는 거의 없으며 많은 서버의 기본 연결 시간 제한은 다소 짧습니다 (예 : Apache httpd 2.2 이상에서는 5 초).
이 org.apache.http.NoHttpResponseException
오류는 서버에 의해 닫힌 하나의 지속적인 연결에서 발생했을 가능성이 높습니다.
사용하지 않는 연결을 Apache Http 클라이언트 풀에서 열린 상태로 유지하는 최대 시간을 밀리 초 단위로 설정할 수 있습니다.
Spring Boot를 사용하여이를 달성하는 한 가지 방법 :
public class RestTemplateCustomizers {
static public class MaxConnectionTimeCustomizer implements RestTemplateCustomizer {
@Override
public void customize(RestTemplate restTemplate) {
HttpClient httpClient = HttpClientBuilder
.create()
.setConnectionTimeToLive(1000, TimeUnit.MILLISECONDS)
.build();
restTemplate.setRequestFactory(
new HttpComponentsClientHttpRequestFactory(httpClient));
}
}
}
// In your service that uses a RestTemplate
public MyRestService(RestTemplateBuilder builder ) {
restTemplate = builder
.customizers(new RestTemplateCustomizers.MaxConnectionTimeCustomizer())
.build();
}
This can happen if disableContentCompression()
is set on a pooling manager assigned to your HttpClient, and the target server is trying to use gzip compression.
Same problem for me on apache http client 4.5.5 adding default header
Connection: close
resolve the problem
Although accepted answer is right, but IMHO is just a workaround.
To be clear: it's a perfectly normal situation that a persistent connection may become stale. But unfortunately it's very bad when the HTTP client library cannot handle it properly.
Since this faulty behavior in Apache HttpClient was not fixed for many years, I definitely would prefer to switch to a library that can easily recover from a stale connection problem, e.g. OkHttp.
Why?
- OkHttp pools http connections by default.
- It gracefully recovers from situations when http connection becomes stale and request cannot be retried due to being not idempotent (e.g. POST). I cannot say it about Apache HttpClient (mentioned
NoHttpResponseException
). - Supports HTTP/2.0 from early drafts and beta versions.
When I switched to OkHttp, my problems with NoHttpResponseException
disappeared forever.
I have faced same issue, I resolved by adding "connection: close" as extention,
Step 1: create a new class ConnectionCloseExtension
import com.github.tomakehurst.wiremock.common.FileSource;
import com.github.tomakehurst.wiremock.extension.Parameters;
import com.github.tomakehurst.wiremock.extension.ResponseTransformer;
import com.github.tomakehurst.wiremock.http.HttpHeader;
import com.github.tomakehurst.wiremock.http.HttpHeaders;
import com.github.tomakehurst.wiremock.http.Request;
import com.github.tomakehurst.wiremock.http.Response;
public class ConnectionCloseExtension extends ResponseTransformer {
@Override
public Response transform(Request request, Response response, FileSource files, Parameters parameters) {
return Response.Builder
.like(response)
.headers(HttpHeaders.copyOf(response.getHeaders())
.plus(new HttpHeader("Connection", "Close")))
.build();
}
@Override
public String getName() {
return "ConnectionCloseExtension";
}
}
Step 2: set extension class in wireMockServer like below,
final WireMockServer wireMockServer = new WireMockServer(options()
.extensions(ConnectionCloseExtension.class)
.port(httpPort));
참고URL : https://stackoverflow.com/questions/10558791/apache-httpclient-interim-error-nohttpresponseexception
'IT Share you' 카테고리의 다른 글
Fabric을 사용하여 원격 쉘에서 run () 호출을 할 때 오류 코드를 포착 할 수 있습니까? (0) | 2020.11.20 |
---|---|
상태 비 저장과 상태 저장 시스템의 차이점은 무엇이며 병렬 처리에 어떤 영향을 줍니까? (0) | 2020.11.20 |
모듈 함수 대 staticmethod 대 classmethod 대 장식 자 없음 : 어떤 관용구가 더 파이썬 적일까요? (0) | 2020.11.20 |
Bash 스크립트 오류 : "기능 : 찾을 수 없음". (0) | 2020.11.20 |
Node js 파일에서 폴더 경로 가져 오기 (0) | 2020.11.20 |