Solução de problemas de produção org.apache.http.NoHttpResponseException: 127.0.0.1:9000 falhou ao responder

No ambiente de produção, o solicitante chama nosso endereço e ocorre uma exceção NoHttpResponseException. Detalhes do erro:

org.apache.http.NoHttpResponseException: 127.0.0.1:9000 failed to respond
	at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:141)
	at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
	at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
	at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163)
	at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:157)
	at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273)
	at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272)
	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
	at com.http.CommonHttpClient.sendPost(CommonHttpClient.java:96)
	at com.http.CommonHttpClient.lambda$main$0(CommonHttpClient.java:121)
	at java.util.stream.ForEachOps$ForEachOp$OfInt.accept(ForEachOps.java:205)
	at java.util.Spliterators$IntArraySpliterator.forEachRemaining(Spliterators.java:1032)
	at java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:693)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:291)
	at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool$WorkQueue.execLocalTasks(ForkJoinPool.java:1040)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1058)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)

Olhando o código-fonte do erro, os comentários relevantes indicam que o servidor fechou a conexão:
Insira a descrição da imagem aqui
Para resolver o problema, primeiro você precisa reproduzi-lo, então inicie o serviço localmente e defina o tempo de keepalive do Tomcat para 1s.

server:
  tomcat:
    keep-alive-timeout: 1000

Use o pool de conexões common-httpclient4.5.10 para simular a solicitação. Aqui estão as configurações:

connManager.setMaxTotal(5);
connManager.setDefaultMaxPerRoute(5);

Como a conexão é um conjunto de abstrações ip:port, obtenha a porta de conexão local no código de simulação, simule 20 solicitações no teste principal, durma um pouco após enviar a solicitação, empurre a conexão para expirar e o servidor fecha o conexão:

BasicHttpContext httpContext = new BasicHttpContext();
final long l = System.currentTimeMillis();
try {
    
    
    response = httpClient.execute(httpPost, httpContext);
    local = JSONObject.parseObject(JSON.toJSONString(httpContext.getAttribute("http.connection"))).getString("localPort");
    HttpEntity httpEntity = response.getEntity();
    result = EntityUtils.toString(httpEntity, "utf-8");
    System.out.println("normal" + " : " + l + " : " + result + " : " + local);
} catch (Exception e) {
    
    
    System.out.println("error " + " : " + l + " : " + local);
    e.printStackTrace();
}
-----------------------------------------------------------------------------------
public static void main(String[] args) {
    
    
        try {
    
    
            IntStream.range(1, 20).parallel().sorted().forEach(e -> {
    
    
                try {
    
    
                    sendPost("http://127.0.0.1:9000/receive", "{
    
    }");
                    TimeUnit.MILLISECONDS.sleep(995L);
                } catch (Exception exception) {
    
    
                    exception.printStackTrace();
                }
            });
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

Insira a descrição da imagem aqui
Pode-se observar que há um total de 5 conexões entre o local e o servidor, 51573, 51574, 51575, 51576, 51577. Duas delas possuem dados anormais e relatórios de erros: NoHttpResponseException. As duas conexões de porta de 75 e 76 possuem não foi usado posteriormente e há suspeita de ter sido fechado. Dê uma olhada nos dados de captura de pacotes: a
Insira a descrição da imagem aqui
conexão foi realmente fechada acenando quatro vezes nessas duas portas. Parece que a conexão não está mais disponível e um erro foi retornado ao iniciar a solicitação. Se a conexão estiver indisponível, o pool de conexões limpará a conexão indisponível e recriará uma nova conexão. Vamos dar uma olhada na política keep-alive padrão do httpclient:
Insira a descrição da imagem aqui
o problema também ocorreu e os motivos relacionados foram basicamente determinados.A solução é garantir a disponibilidade da conexão:
1. Desligue o keep-alive e defina o cabeçalho Connection close
2 . Implementar keep-alive na estratégia do cliente, o tempo é menor que o tempo limite de keep-alive do servidor, a conexão expira e é liberada mais cedo; é claro, um tamanho de pool de conexão razoável deve ser configurado, não muito grande. 3 . Quando tal erro ocorre no cliente, o mecanismo de nova tentativa deve ser
habilitado

Acho que você gosta

Origin blog.csdn.net/weixin_43275277/article/details/132192156
Recomendado
Clasificación