IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 一次线上http连接被拒绝问题的排查 -> 正文阅读

[网络协议]一次线上http连接被拒绝问题的排查

线上环境连第三方的HTTP服务时报连接被拒绝,单独通过curl命令发现也是返回连接被拒绝,把问题反馈给第三方后得到的答复是他们有设置最大连接数为300,要我方自查代码。

赶紧自查代码后发现确实代码有问题:

public static CloseableHttpClient newInstance(String ip_port, String userName, String password) {

         。。。。。此处省略无关代码
           CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm)
            			.setDefaultRequestConfig(defaultRequestConfig)
            			.setDefaultCredentialsProvider(provider).build();

            return httpClient;
        }
    }

上述代码在每次调用newInstance时都创建了一个 httpClient ,如果并发高的话会导致创建大量的连接请求,最终导致第三方拒绝请求,问题找到后,赶紧将httClient修改成了单例模式,一顿操作操作猛如虎,发布到SIT环境信心满满进行测试,结果连接数量似乎是控制住了,但是多刷几次页面后又报了Timeout waiting for connection from pool,看到这个错误后马上想到是池里的连接被占用没有释放出来,于是又自查代码如下:

try {
           。。。此处省略无关代码
            String responseXml = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            。。。此处省略无关代码
        } catch (Exception e) {
            throw e;
        }

使用了EntityUtils.toString对返回的body进行处理,追踪进入EntityUtils.toString的源码后,发现其有在finally中关闭流,到此似乎有点懵了,线索断了。只好再次深翻错误日志,发现在抛出Timeout waiting for connection from pool错误之前已经有抛出自定义的异常了,然后根据异常堆栈信息追查到代码处后豁然开朗:抛出异常后不会走上述代码的EntityUtils.toString自然也就没有释放连接了,最终修改如下:

try {
           。。。此处省略无关代码
            String responseXml = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            。。。此处省略无关代码
        } catch (Exception e) {
            throw e;
        }finally {
        	EntityUtils.consumeQuietly(response.getEntity());
        }

再次测试OK。

总结一下:

在实际项目中如果没有考虑到对HttpClient或者CloseableHttpClient进行正确的释放连接操作,则会带来生产问题,后面的请求一直无法获取到连接资源,导致并发起不来。很多同学可能并没有遇到过这个问题是因为HttpClient或者CloseableHttpClient并不是单例的,而是每次使用时都创建新的实例,在正常情况下你可能正确地释放了连接,但一定要考虑到异常情况下的连接释放,正确的做法是确保释放连接的操作是在finally块中。

另外对于HttpClient或者CloseableHttpClient的创建还是不要太随意,尽量使用一个全局的(除非你有迫不得已的原因),同时设置好连接池等相关优化配置,这里着重解释下连接池配置的两个重要参数,MaxTotal表示池里最大的连接数量,DefaultMaxPerRoute按字面理解是每个路由的最大连接数(其实就是你对同一个目标服务器请求的最大连接数),此处千万不要被MaxTotal所迷惑,一定要结合DefaultMaxPerRoute参数来判断最大连数是多少。

另外CloseableHttpClient中的execute()有多个重载方法,而实际调用后能释放资源的execute必须是包含ResponseHandler<? extends T>这个属性的,否则和原有HttpClient方式是一样的。在使用EntityUtils.toString()方法时,虽然其底层调用会执行InputStream关闭流,但是这里也可能是坑之所在,当你请求第三方超时或其他异常时,会直接跳过,并没有执行上面的toString()方法,那么就不会释放连接资源。

针对CloseableHttpClient有下述两种释放连接的方案:

1、确保释放连接的操作是在finally块中。

2、使用包含ResponseHandler这个属性的execute方法

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-05-01 16:06:29  更:2022-05-01 16:07:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/30 3:01:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码