3.9K Star 22.7K Fork 7.8K

GVPdromara / hutool

 / 详情

httpUtil 访问第三方服务线程一直卡死,设置超时时间后 报读超时异常

已完成
创建于  
2022-10-18 13:52

版本情况

JDK版本: openjdk_8_201
hutool版本: 5.8.8(请确保最新尝试是否还有问题)

问题描述(包括截图)

合作的第三方对外提供了一个http接口,使用postman可以访问并能正常返回结果,使用hutool httputil 线程一直卡死
等待在那里,后通过tcp客户端进行模拟,抓包的内容如下,模拟步骤如下,我本地起了一个8883的tcpserver,然后运下方hutool代码,建立http连接, 发送上述POSTMAN成功返回体内容, hutool工具一直卡死等待,一直等到我这边服务端手动断开连接之后, hutool才把内容打印出来,而使用postman访问模拟的tcpserver时,tcpserver发送完成之后,连接就自动关闭了,并且postman客户端能正常返回json内容,使用apache client 也能正常访问,使用jdk原生HttpURLConnection对象也会出现同样的问题,给人的感觉是服务端的问题,服务端是c++编写比较简陋,且代码不可见,但使用postman就能访问,不知道问题出在哪,能否通过在客户端设置)一些参数解决该问题。

POSTMAN 请求体
GET /api/test/testGetWithBodyParam HTTP/1.1
Content-Type: application/json
User-Agent: PostmanRuntime/7.26.8
Accept: /
Postman-Token: cc1818a7-a983-4340-a3a8-8e3bff55f196
Host: 127.0.0.1:8883
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 15

{"name" :"aaa"}

返回体

HTTP/1.1 200 Request is completed
Content-Type : application/json;charset=utf-8
Cache-Control : no-cache
Connection : close
Content-Length : 34

{"taskID": 370, "flightID" : 2879}

  1. 复现代码
    JSONObject jsonObject2 = new JSONObject();
    jsonObject2.putOpt("name", "370");
    String body2 = HttpRequest.get("http://127.0.0.1:8883/api/test/testGetWithBodyParam").
    body(JSONUtil.toJsonStr(jsonObject2)).
    execute().body();
    System.out.println(body2);

  2. 堆栈信息

  3. 测试涉及到的文件(注意脱密)
    使用tcp工具模拟截图 https://foruda.gitee.com/images/1666072677292275454/694fb8cc_682663.jpeg
    postman访问可以正常返回,hutool访问卡死 需要手动在服务端关闭连接,才能读到内容。

评论 (7)

sony_7 创建了任务
sony_7 修改了描述
sony_7 修改了描述
展开全部操作日志

不好复现。
大概率是服务端的问题。
你先设置超时时间:

String body2 = HttpRequest.get("http://127.0.0.1:8883/api/test/testGetWithBodyParam")
//设置超时时间
.timeout(2000)
.body(JSONUtil.toJsonStr(jsonObject2))
execute().body();

已经试过了,设置超时时间后,到达超时时间后连接断开,报读超时异常,可以复现,用tcp工具开启一个server,hutool进行发送,上面有个模拟的截图

@sony_7 尝试修改下User-Agent,是不是服务端封掉你了。

又测试了一下,不知道是不是这个原因,先说现象,hutool httputil 中似乎并没有对服务端响应报文中的Connection字段进行处理,无论是close,还是keep-alive,在处理完返回体之后
连接都是一直处于活动的状态(通过tcp模拟工具进行观察),这个时候线程一直处于挂起状态,即使设置了超时时间,也会报读超时异常,然后我又在tcp模拟工具中把该连接关闭,此hutool挂起的线程继续执行,就可以打出了返回体的内容,猜测hutool 一但在服务器端发送完响应报文时候没有主动关闭连接,就会出现该问题,
实际上这步应该在客户端解析完 Connection的值后进行断开连接处理(结论是通过apache client进行得出 下面贴出模拟的图)
apache模拟1.png
apache模拟2.png
hutool模拟1
hutool模拟2.png

//测试代码
Map<String, Object> map = new HashMap<>();
map.put("taskID", 370);
map.put("flightID", 2879);
//-------------------------------使用apache client 进行访问-----------------------//
//创建httpclient对象
CloseableHttpClient client = HttpClients.createDefault();
HttpGetWithEntity httpGetWithEntity = new HttpGetWithEntity("http://127.0.0.1:8884/api/test/testHttpUtilGetWithBody");
HttpEntity httpEntity = new StringEntity(JSONUtil.toJsonStr(map), ContentType.APPLICATION_JSON);
httpGetWithEntity.setEntity(httpEntity);
//执行请求操作,并拿到结果(同步阻塞)
CloseableHttpResponse response = client.execute(httpGetWithEntity);
//获取结果实体
HttpEntity entity = response.getEntity();
if (entity != null) {
//按指定编码转换结果实体为String类型
String body = EntityUtils.toString(entity, "utf-8");
System.out.println("Apache client客户端请求返回结果:" + body);
}
//释放链接
response.close();
//防止函数执行完成之后,main方法退出,导致连接退出
while (true){
ThreadUtil.safeSleep(1);
}
//-------------------------------使用apache client 进行访问-----------------------//
//-------------------------------使用hutool 进行访问-----------------------//
String body = HttpRequest.get("http://127.0.0.1:8884/api/test/testHttpUtilGetWithBody").body(JSONUtil.toJsonStr(map)).execute().body();
System.out.println("使用hutool返回结果:" + body);
//-------------------------------使用hutool 进行访问-----------------------//

@Looly uyong关联的 Pull Request !845:#I5WAV4 修复http请求读取响应时堵塞问题 刚试了一下 并不解决这个问题

@sony_7 经过测试,应该是你的响应报文格式不规范造成的(Postman和HttpClient应该是做了一定的容错)

你的头信息中header部分键值对部分:两边不应该加空格:

HTTP/1.1 200 Request is completed
Content-Type:application/json;charset=utf-8
Cache-Control:no-cache
Connection:close
Content-Length:34

{"taskID": 370, "flightID" : 2879}

这样就正常返回了。

如有问题可继续打开此issue讨论。

Looly 任务状态待办的 修改为已完成
Looly 添加了
 
question
标签

登录 后才可以发表评论

状态
负责人
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
参与者(3)
1463 loolly admin 1578914022
Java
1
https://gitee.com/dromara/hutool.git
git@gitee.com:dromara/hutool.git
dromara
hutool
hutool

搜索帮助

344bd9b3 5694891 D2dac590 5694891