首页 > 其他分享 >HttpClient报错 org.apache.http.NoHttpResponseException : 10.1.1.0:13001 failed to respond 解决

HttpClient报错 org.apache.http.NoHttpResponseException : 10.1.1.0:13001 failed to respond 解决

时间:2023-11-06 18:05:54浏览次数:40  
标签:10.1 respond return final httpClientBuilder 报错 new 连接 服务端

一、问题描述

使用 HttpClient 并发调用http 接口,并发量稍微大一点就会报错

org.apache.http.NoHttpResponseException : 10.1.1.0:13001 failed to respond 

二、排查过程

  1. 最开始怀疑是服务端连接过多,拒绝请求了,监控发现服务端并没有多少连接
  2. 找运维搭建了一个新环(只有我们请求服务端),发现只要并发大一点,必定会出现此错误
  3. 网上一通找,主要有这几个解决方法

a、添加自定义重试策略,在重试策略中判断异常如果是NoHttpResponseException,就重试

HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
httpClientBuilder.setRetryHandler(new HttpRequestRetryHandler() {
            @Override
            public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
                if (exception instanceof NoHttpResponseException) {
                    //NoHttpResponseException 异常重试
                    return true;
                }
                
                if (executionCount >= 3) {
                    return false;
                }
                
                return false;
            }

b、减小validateAfterInactivity配置时间(这个配置是在从连接池获取连接时校验连接可用的间隔时间,默认2s)

PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(
            socketFactoryRegistry);
poolingHttpClientConnectionManager.setValidateAfterInactivity(1);

     c、直接关闭连接重用,即 

HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
httpClientBuilder.setConnectionReuseStrategy(new DefaultConnectionReuseStrategy(){
            @Override
            public boolean keepAlive(HttpResponse response, HttpContext context) {
              //不重用连接
                return false;
            }
        });
  1. 但可惜,这三种都不能最终非常优雅的解决问题
  1. 重试虽然能解决这种问题,但是网络存在问题也可能会出现这种问题,可能请求已经发到服务器上了,只是最后响应没有写回,重试可能导致重复请求,存在风险,pass 掉
  2. 减小这个配置,虽然可以减低报错概率,但是并发非常大或者说请求很频繁的话,还是存在较低概率发生报错,pass 掉
  3. 直接不复用连接,那 httpclient 连接池的作用就不大了,影响性能,pass 掉(如果没有更好的办法就使用这个)
  1. 最后通过debug客户端和服务端的代码,发现服务端居然是短链接,每次返回响应就主动断掉连接(服务端使用的是 Netty Http服务)
  2. 有同事说反正服务端是短链接,那我们就使用第三种方案得了。但是我们不是只调用一个服务,其他好几个服务也是通过这个连接池调用的,可以说是一个工具类,不能直接这样改掉
  3. 最终采取了一个折中方案,采用第二、第三种方案结合的方式,解决此问题
  1. 自定义重用连接的策略
  2. 如果服务端的响应 header 带了 Connection=close,则不复用连接
  3. 如果服务端连接已不可用,则不复用连接(即调用第二种方式去校验连接是否可用)
  4. 其他情况复用连接
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
httpClientBuilder.setConnectionReuseStrategy(CustomClientConnectionReuseStrategy.INSTANCE);

public class CustomClientConnectionReuseStrategy extends DefaultConnectionReuseStrategy {
    public static final CustomClientConnectionReuseStrategy INSTANCE = new CustomClientConnectionReuseStrategy();

    @Override
    public boolean keepAlive(final HttpResponse response, final HttpContext context) {
        final HttpRequest request = (HttpRequest) context.getAttribute(HttpCoreContext.HTTP_REQUEST);
        if (request != null) {
            final Header[] connHeaders = request.getHeaders(HttpHeaders.CONNECTION);
            if (connHeaders.length != 0) {
                final TokenIterator ti = new BasicTokenIterator(new BasicHeaderIterator(connHeaders, null));
                while (ti.hasNext()) {
                    final String token = ti.nextToken();
                    if (HTTP.CONN_CLOSE.equalsIgnoreCase(token)) {
                        //请求头自带 connection:close,不复用连接
                        return false;
                    }
                }
            }
        }

        final Object obj = context.getAttribute(HttpCoreContext.HTTP_CONNECTION);
        if (obj instanceof HttpConnection) {
            //连接是否已经关闭或者失效,不复用连接
            return !((HttpConnection) obj).isStale();
        }

        return super.keepAlive(response, context);
    }

}

标签:10.1,respond,return,final,httpClientBuilder,报错,new,连接,服务端
From: https://blog.51cto.com/u_16206170/8215042

相关文章

  • Java中的NoClassDefFoundError报错解析
    半夜睡得正香的时候,突然接到警告电话,于是翻起身就打卡电脑连上环境查看是什么情况?登录上之后发现有个微服务占用的句柄数量一直在持续上涨,最终导致了微服务内存溢出挂掉了。这个微服务在运行的过程中会建立SSH连接,且之前这个微服务已经遇到过很多次类似的情况了,因此第一反应是哪里......
  • 报错:1130-host ... is not allowed to connect to this MySql server 开放mysql远程
    报错:1130-host...isnotallowedtoconnecttothisMySqlserver开放mysql远程连接不使用localhost解决方法:1。改表法。可能是你的帐号不允许从远程登陆,只能在localhost。这个时候只要在localhost的那台电脑,登入mysql后,更改"mysql"数据库里的"user"表里的"host"项,从"......
  • mac os 编译webrtc 报错screen_capturer_mac.mm:500:5: error: 'CGDisplayStreamStop'
    ../../modules/desktop_capture/mac/screen_capturer_mac.mm:462:11:error:'CGDisplayStreamUpdateGetRects'isonlyavailableonmacOS13.0ornewer[-Werror,-Wunguarded-availability-new]462|CGDisplayStreamUpdateGetRects(updateRef,kC......
  • jupyter 下 bitandbytes报错记录
    背景:在jupyter中加载baichuan大模型时报错报错一:frompeftimportPeftModel 报错报错提示:python-mbitsandbytes执行python-mbitsandbytes时又报错,报错内容为:Traceback(mostrecentcalllast):File"/home/miniconda3/envs/vllm/lib/python3.10/runpy.py",lin......
  • 使用uniapp开发小程序getLocation报错
    uniapp中使用uni.getLocation()报错,报错如下:getLocation:failtheapineedtobedeclaredintherequiredPrivateInfosfieldinapp.json/ext.json 首先检查uniapp的manifest文件发现位置权限已经开启: 后翻阅微信文档后发现原来是微信官方做了调整,uniapp只勾选这个还......
  • jsqlparser v4.6 版本下sql解析报错
    项目版本:springboot2.7.2mybatis-plus3.5.2jsqlparser4.6该版本下mybatis-plus生成的sql文件带有连续\n\n\nCCJSqlParserUtil.parseStatements("select\n\n\n*from\n\ndual\n")再使用jsqlparser进行sql解析时会出现如下报错net.sf.jsqlparser.parser.ParseExc......
  • Python_pytest +文件名,报错—— zsh: command not found: pytest
     原因:由于“通过pip安装pytest不会使其成为系统命令,而是会将其安装到python”“-m命令将pytest作为其自己的命令运行,然后任何后续脚本都将作为参数。”解决:所以我们在命令窗口执行时应该在.py文件所在路径下执行  python-mpytest-vtest_wework.py这个问题终于......
  • 解决适用EntityFramework生成时报错“无法解析依赖项。"EntityFramework 6.4.4" 与 '
    点击添加,出现错误提示:......
  • R语言install.packages("jpeg")报错
    R语言install.packages("jpeg")时报错Infileincludedfromread.c:1:0:rjcommon.h:11:21:fatalerror:jpeglib.h:Nosuchfileordirectoryrjcommon.h:11:21:致命错误:jpeglib.h:没有那个文件或目录#include<jpeglib.h>compilationterminated.make:***[read.o]Error......
  • Mac OS 10.15 安装 java 1.8
     1.到Oracle官网下载JDK1.8安装包 选择接受证书协议,然后选择对应的MacOSX一栏下载SDK,下载sdk必须要登录才可以下载,大家有需要的可以点击这里,百度网盘提取码:c62d下载完成后,我们得到一个dmg的安装包,名称为jdk-8u211-macosx-x64.dmg,表示这是java8版本号为211的JDK安装包。 2......