httpClient超时时间详解与测试案例

使用httpclient作为http请求的客户端时,我们一般都会设置超时时间,这样就可以避免因为接口长时间无响应或者建立连接耗时比较久导致自己的系统崩溃。通常它里面设置的几个超时时间如下:

RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(3000).setConnectTimeout(3000).setSocketTimeout(3000).build();

setConnectionRequestTimeout():从httpclient连接池中获取连接的超时时间,如果连接池中的连接都被占用,那么超过该时间还未获取到连接就会抛出异常。
setConnectTimeout():建立连接发生三次握手时的超时时间,如果超过该设置的时间连接还未建立成功就会抛出异常。
setSocketTimeout():读取数据超时时间,注意这个时间不是接口响应耗时时间,是接口返回数据两次数据包之间间隔时间,如果超过这个时间间隔还没有新的数据返回,那么就会抛出异常。

下面就分别测试三种超时时间:
在测试超时时间前,需要创建一个接口用于请求:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;/*** 测试接口* * @Author xingo* @Date 2023/11/15*/
@RestController
public class DemoController {@GetMapping("/demo1")public String socketTimeout() throws InterruptedException {TimeUnit.MILLISECONDS.sleep(5000);return "ok";}@GetMapping("/demo2")public void socketTimeout2(HttpServletResponse response) throws InterruptedException, IOException {for (int i = 0; i < 10; i++) {System.out.println(i);response.getWriter().print(i);response.flushBuffer();TimeUnit.MILLISECONDS.sleep(800);}}
}
  1. 从连接池获取连接超时:
    要想测试连接超时时间,需要调整连接池大小,有关连接池配置请参考:httpclient工具类封装 ,这里有两个参数:
// 连接池配置
PoolingHttpClientConnectionManager poolingManager = new PoolingHttpClientConnectionManager(sf);
// 最大连接数
poolingManager.setMaxTotal(2);
// 每个路由最大连接数
poolingManager.setDefaultMaxPerRoute(2);

将两个连接池参数调整为2个,这样就可以很快达到线程池大小,设置一段循环代码一直请求上面的耗时接口:http://localhost:8081/demo1 。测试代码如下:

/*** @Author xingo* @Date 2023/11/15*/
public class TestHttpUtils {public static void main(String[] args) {final String url = "http://localhost:8081/demo1";for(int i = 0; i < 10; i++) {new Thread(() -> {HttpResult result = HttpUtils.getInstance().doGet(url, null, null, "UTF-8", 10000, 1000, 100);System.out.println(result.getBody());}, "thread-" + i).start();}}
}

这里面从连接池中获取连接超时时间设置为100ms,而请求响应耗时是5s,这样很快就会达到线程池大小而不会返回连接,这个测试代码会抛出如下异常:

org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from poolat org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:316)at org.apache.http.impl.conn.PoolingHttpClientConnectionManager$1.get(PoolingHttpClientConnectionManager.java:282)at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:190)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 org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)at org.example.config.HttpUtils.doGet(HttpUtils.java:677)at org.example.config.TestHttpUtils.lambda$main$0(TestHttpUtils.java:22)at java.lang.Thread.run(Thread.java:748)

所以当项目中的请求并发量比较大,而且耗时较久时就需要调整几个参数:第一个就是连接池大小和单个路由的连接数量;第二个就是要调整从连接池中获取连接的超时时间,避免获取连接超时。

  1. 建立连接超时
    建立连接超时一般是服务端无响应或者服务端无法快速建立连接导致的三次握手超时,这时候就会抛出连接超时异常,如我们调整连接地址为:http://localhost:8082/demo1 。这是一个根本不存在的服务,这时调整测试代码:
/*** @Author xingo* @Date 2023/11/15*/
public class TestHttpUtils {public static void main(String[] args) {final String url = "http://localhost:8082/demo1";HttpResult result = HttpUtils.getInstance().doGet(url);System.out.println(result.getBody());}
}

这时就会抛出建立连接异常:

org.apache.http.conn.HttpHostConnectException: Connect to localhost:8082 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connectat org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:156)at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)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 org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)at org.example.config.HttpUtils.doGet(HttpUtils.java:677)at org.example.config.HttpUtils.doGet(HttpUtils.java:584)at org.example.config.TestHttpUtils.main(TestHttpUtils.java:11)
Caused by: java.net.ConnectException: Connection refused: connectat java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)at java.net.Socket.connect(Socket.java:589)at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:75)at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)... 12 more
  1. 响应超时
    响应超时是获取服务端返回数据超时,但是这里的超时不是服务端返回数据整个过程超时,而是返回两个数据包之间的时间间隔超过设置的超时时间。
    测试的第二个接口返回数据分多次输出,每次输出数据间隔是800ms,整个响应耗时是8s。第一次测试设置超时时间是1s,超过两次时间间隔,这时不会发生读取数据超时:
/*** @Author xingo* @Date 2023/11/15*/
public class TestHttpUtils {public static void main(String[] args) {final String url = "http://localhost:8081/demo2";HttpResult result = HttpUtils.getInstance().doGet(url, 1000);System.out.println(result.getBody());}
}

结果正常输出:0123456789
如果将超时时间设置为500ms,就会发生读取数据超时异常:

java.net.SocketTimeoutException: Read timed outat java.net.SocketInputStream.socketRead0(Native Method)at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)at java.net.SocketInputStream.read(SocketInputStream.java:171)at java.net.SocketInputStream.read(SocketInputStream.java:141)at org.apache.http.impl.conn.LoggingInputStream.read(LoggingInputStream.java:84)at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:137)at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:153)at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:280)at org.apache.http.impl.io.ChunkedInputStream.getChunkSize(ChunkedInputStream.java:261)at org.apache.http.impl.io.ChunkedInputStream.nextChunk(ChunkedInputStream.java:222)at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:183)at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:135)at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)at java.io.InputStreamReader.read(InputStreamReader.java:184)at java.io.Reader.read(Reader.java:140)at org.apache.http.util.EntityUtils.toString(EntityUtils.java:227)at org.apache.http.util.EntityUtils.toString(EntityUtils.java:270)at org.apache.http.util.EntityUtils.toString(EntityUtils.java:290)at org.example.config.HttpUtils.doGet(HttpUtils.java:680)at org.example.config.HttpUtils.doGet(HttpUtils.java:594)at org.example.config.TestHttpUtils.main(TestHttpUtils.java:11)

以上三个超时时间就是在使用apache的httpclient时需要注意的,避免因为设置错误导致程序崩溃。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/144094.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电磁场与电磁波part1--矢量分析

目录 1、方向导数 2、散度定理&#xff08;高斯定理&#xff09; 3、散度与旋度的比较 4、旋度定理&#xff08;斯托克斯定理&#xff09; 5、关于点乘、叉乘、梯度、散度、旋度的计算 ~~~~~~~~~~~~~~~~~~~~~~~~ 确认过眼神&#xff0c;是我看不懂的 ~~~~~~~~~~~~~~~~…

IDEA没有Add Framework Support解决办法

点击File—>Settings 点击第一个设置快捷键 点击apply和ok即可 我们要点击一下项目&#xff0c;再按快捷键ctrlk 即可

C++入门(2)—函数重载、引用

目录 一、函数重载 1、参数类型不同 2、参数个数不同 3、参数顺序不同 4、 链接中如何区分函数重载 二、引用 1、规则 2、特征 3、使用场景 做参数 做返回值 4、常引用 5、传值、传引用效率比较 6、引用和指针的区别 接上一小节C入门(1)—命名空间、缺省参数 一…

Python 如何实现适配器设计模式?什么是适配器(Adapter)设计模式?

什么是适配器设计模式&#xff1f; 适配器&#xff08;Adapter&#xff09;设计模式是一种结构型设计模式&#xff0c;它允许接口不兼容的类之间进行合作。适配器模式充当两个不兼容接口之间的桥梁&#xff0c;使得它们可以一起工作&#xff0c;而无需修改它们的源代码。 主要…

JXLS 导出多sheet,带页眉页脚

/*** 生成多sheet Excel* 带自定义页眉页脚** param templatePath* param sheetList* return* throws IOException*/public static byte[] generateMultiSheet(String templatePath, List<JxlsHelper2.SheetContext> sheetList) throws IOException {ByteArrayOutputStre…

C++ 基础

准备工具Vscode或者Clion或者Dev C或者Vs studio 和 MSYS2 是C跨平台的重要工具链. 基础一 准备工作安装MSYS2软件 创建文件 一、基本介绍1.1C源文件1.2 代码注释1.3变量与常量1.3.1变量1.3.2 常量1.3.3 二者的区别&#xff1a; 1.4 关键字和标识符 二、数据类型2.1 基本数据类…

Flink CDC

1、Flink CDC的介绍&#xff1a; 是一种技术&#xff0c;可以帮助我们实时的捕获数据库中数据的变化&#xff0c;并将这些变化的数据以流的形式传输到其他的系统中进行处理和存储。 2、Flink CDC的搭建&#xff1a; 1、开启mysql的binlog功能&#xff1a; # 1、修改mysql配置…

C/C++ 实现获取硬盘序列号

获取硬盘的序列号、型号和固件版本号&#xff0c;此类功能通常用于做硬盘绑定或硬件验证操作&#xff0c;通过使用Windows API的DeviceIoControl函数与物理硬盘驱动程序进行通信&#xff0c;发送ATA命令来获取硬盘的信息。 以下是该程序的主要功能和流程&#xff1a; 定义常量…

2023版Idea创建JavaWeb时,右键new没有Servlet快捷键选项

问题&#xff1a;右键时&#xff0c;没有创建servlet的快捷键&#xff0c;如下图&#xff1a; 解决方法&#xff1a; 1.打开idea&#xff0c;点击File>settings(设置)&#xff0c;进入settings页面&#xff0c;如下 从上图中的Files选项中没看到有servlet选项&#xff0c;…

2023NOIP A层联测32

2023NOIP A层联测32 文章目录 2023NOIP A层联测32A flandreB.meirinC.sakuyaD. 红楼 ~ Eastern Dream总结 A flandre 有 n n n 种烟花&#xff0c;每种烟花有两个参数 a &#xff0c; b a &#xff0c; b a&#xff0c;b&#xff0c;你要构造一种燃放顺序&#xff0c;使得 …

正则表达式入门教程

一、本文目标 让你明白正则表达式是什么&#xff0c;并对它有一些基本的了解&#xff0c;让你可以在自己的程序或网页里使用它。 二、如何使用本教程 文本格式约定&#xff1a;专业术语 元字符/语法格式 正则表达式 正则表达式中的一部分(用于分析) 对其进行匹配的源字符串 …

Rancher 容器中使用 jmap 工具导出内存日志

提升容器权限 编辑容器工作负载&#xff0c;在【安全/主机设置】中选中【特权模式】的【是&#xff1a;容器具有所有主机访问权限】 进入容器命令行&#xff0c;执行 jmap 命令 # 获取服务 pid ps -ef | grep java # 执行 jmap 导出内存日志 jmap -dump:live,formatb,file/hom…

线程锁的应用与示例代码

为了解决这个问题&#xff0c;可以使用线程锁来确保在提取zip文件中的每个文件时&#xff0c;同一时间只有一个线程可以访问文件。这样可以避免多个线程同时访问和写入文件&#xff0c;从而解决race condition的问题。以下是修改后的示例代码&#xff1a; python import reque…

提升pip速度!设置pip全局镜像源,速度飞起!

文章目录 💢 问题 💢💯 解决方案 💯🐾 镜像源🐾 镜像全局配置🍄 Windows系统🍄 Linux和macOS系统🍄 添加环境变量的方式💢 问题 💢 由于“某些网络限制”原因,我们在使用pip安装python模块的时候速度会比较慢,这个时候我们就需要用到一些镜像源,本文将…

R语言提取文字(字符串)中的内容--正则式(2)

科学研究中有时候咱们收集到的数据很乱&#xff0c;不能马上进行分析&#xff0c;如SEER数据&#xff0c;用过都知道&#xff0c;咱们需要对数据进行清洗&#xff0c;从数据中提取咱们需要的东西&#xff0c;才能进行分析&#xff0c;这时候有个有用的东西叫正则式&#xff0c;…

Service Worker是什么?

Service Worker 是一种在 Web 浏览器中运行的脚本&#xff0c;它独立于网页的上下文&#xff0c;并且可以在用户关闭网页后仍然在后台运行。Service Worker 可以用于实现许多功能&#xff0c;包括离线缓存、消息推送和网络代理等。 Service Worker 是一种浏览器技术&#xff0…

2023年05月 Python(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 有列表L=[‘UK’,‘china’,‘lili’,“张三”],print(L[-2])的结果是?( ) A: UK B: ‘lili’,‘张三’ C: lili D: ‘UK’,‘china’,‘lili’ 答案:C 列表元素定位 第2题 …

最新宝塔反代openai官方API开发接口详细搭建教程,解决502 Bad Gateway问题

一、前言 宝塔反代openai官方API接口详细教程&#xff0c;实现国内使用ChatGPT502 Bad Gateway问题解决&#xff0c; 此方法最简单快捷&#xff0c;没有复杂步骤&#xff0c;不容易出错&#xff0c;即最简单&#xff0c;零代码、零部署的方法。 二、实现前提 一台海外服务器…

正版软件|Soundop 专业音频编辑器,实现无缝的音频制作工作流程

关于Soundop Soundop 音频编辑器 直观而专业的音频编辑软件&#xff0c;用于录制、编辑、混合和掌握音频内容。 Soundop 是一款适用于 Windows 的专业音频编辑器&#xff0c;可在具有高级功能的直观灵活的工作区中录制、编辑和掌握音频并混音轨道。音频文件编辑器支持波形和频谱…

在Python中使用sqlite3进行数据持久化操作

目录 引言 一、安装sqlite3模块 二、创建数据库连接 三、创建游标对象 四、执行SQL命令 五、提交更改 六、关闭连接 七、使用参数化查询 八、使用ORM进行数据操作 九、备份和恢复数据库 十、处理大量数据 十一、优化查询性能 十二、处理并发访问 十三、处理数据持…