HttpClient报错cn.hutool.http.HttpException: Read timed out

这篇具有很好参考价值的文章主要介绍了HttpClient报错cn.hutool.http.HttpException: Read timed out。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这个错误明面上说是请求等待超时,但是其实真正的问题并不一定是等待超时的问题

错误出现

这个错误出现是一个项目更新以后的出现的这个问题,错误的代码如下:

cn.hutool.http.HttpException: Read timed out
	at cn.hutool.http.HttpResponse.init(HttpResponse.java:511)
	at cn.hutool.http.HttpResponse.initWithDisconnect(HttpResponse.java:484)
	at cn.hutool.http.HttpResponse.<init>(HttpResponse.java:81)
	at cn.hutool.http.HttpRequest.doExecute(HttpRequest.java:1130)
	at cn.hutool.http.HttpRequest.execute(HttpRequest.java:1012)
	at cn.hutool.http.HttpRequest.execute(HttpRequest.java:988)
	at cn.zc.sport.medical.http.HuHttpUtil.httpPost(HuHttpUtil.java:41)
	at cn.zc.sport.medical.task.RequestSending.core(RequestSending.java:138)
	at cn.zc.sport.medical.task.RequestSending.sending(RequestSending.java:77)
	at sun.reflect.GeneratedMethodAccessor35.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84)
	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
	at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
	at java.util.concurrent.FutureTask.runAndReset(Unknown Source)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.net.SocketTimeoutException: Read timed out
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.socketRead(Unknown Source)
	at java.net.SocketInputStream.read(Unknown Source)
	at java.net.SocketInputStream.read(Unknown Source)
	at sun.security.ssl.SSLSocketInputRecord.read(Unknown Source)
	at sun.security.ssl.SSLSocketInputRecord.readHeader(Unknown Source)
	at sun.security.ssl.SSLSocketInputRecord.bytesInCompletePacket(Unknown Source)
	at sun.security.ssl.SSLSocketImpl.readApplicationRecord(Unknown Source)
	at sun.security.ssl.SSLSocketImpl.access$300(Unknown Source)
	at sun.security.ssl.SSLSocketImpl$AppInputStream.read(Unknown Source)
	at java.io.BufferedInputStream.fill(Unknown Source)
	at java.io.BufferedInputStream.read1(Unknown Source)
	at java.io.BufferedInputStream.read(Unknown Source)
	at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)
	at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
	at java.net.HttpURLConnection.getResponseCode(Unknown Source)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(Unknown Source)
	at cn.hutool.http.HttpConnection.responseCode(HttpConnection.java:470)
	at cn.hutool.http.HttpResponse.init(HttpResponse.java:508)
	... 20 common frames omitted

这里解释一下,因为项目使用了hutool这个工具包,并且http请求也是用的hutool包中的HttpRequest,但是其实hutool中的HttpRequest是对httpClient做了封装本质上也是HttpClient报的错

接下来说一下原因:需求是这样的,我们需要做一个服务将这个电脑上的数据和文件发送给服务器,因此发送采用了hotool工具包HttpRequest,一开始项目是没有问题的,但是后面服务器项目更新了之后就出现了这个问题

分析的过程

最早的分析是:

String result = HttpRequest.post(url)
                .header("contentType", "multipart/form-data")
                .form(paramFile)
                .timeout(20000) // 请求等待时间
                .execute().body();

我们认为这个请求超时的时间设置的太短了,因此引发了这个故障,于是我们把原来的20000 设置成了 60000 也就是 一分钟,部署之后服务又开始正常运行了,可是没有几天他又出现了这个问题,因为出现了一个数据量很大的文件,这个文件的处理超过了一分钟,他又报错了,紧接着我设置了2分钟,但是这次的代码审核没有通过,原因是,可能会存在更大的文件。并且在审核的时候拿了一个很大的文件,确实Read Time out又出现了。

紧接着研究了很长时间,最后项目经理给我了思路,他说为什么会这么长的时间,这些时间到底做了什么?

然后,我通过日志分析了整个这个请求的所有的流程,终于发现了问题出在哪里,因为这个请求是发送给另一个项目的接口,一两句话说不清楚,下面用一个简单的图描述一下这个流程:

cn.hutool.http.httpexception: read timed out,spring boot,http,java,服务器
其实当时分析完这个之后,我想到了使用异步MQ的方式,但是这个提议被否决了,原因是需要搭建MQ服务,成本太大。

最终解决方案

最后分析的解决的方式是这样的:

其实在数据服务器接收到文件的时候,上一个数据推送服务的工作已经结束了,他就没必要等了,所以这里采用了异步调用的方式,来执行,后面的文件的处理

这里写一下异步的实现方式:

首先写一个接口类:

/**
 * 异步处理DCM文件
 *
 * @author An
 * @date 2022/11/3 17:59
 */
public interface AsyncDcm {
    @Async
    void DCMDetailWith(MultipartFile multipartFiles, String decrypt, String study_uid);
}

写class实现这个接口:

/**
 * 异步处理DCM文件实现类
 *
 * @author An
 * @date 2022/11/3 18:01
 */
@Log
@Service
public class AsyncDcmImpl implements AsyncDcm {
    @Autowired
    private Zip4jUtil zip4jUtil;

    @Autowired
    private FileExists fileExists;

    @Value("${file.zipPath}")
    private String zipPath;

    @Value("${file.filePath}")
    private String filePath;

    @Value("${file.jpgPath}")
    private String jpgPath;

    @Autowired
    private OrthancPacsRestTemplate pacsRestTemplate;


    @Override
    public void DCMDetailWith(MultipartFile multipartFiles, String decrypt, String study_uid) {
        // 图片影像dcm文件处理
        if(multipartFiles != null) {
            // 创建缓存目录
            fileExists.directory(zipPath);
            fileExists.directory(filePath);
            fileExists.directory(jpgPath);
            // 清理缓存
            //zip4jUtil.emptyFile(zipPath);
            zip4jUtil.emptyFile(filePath);
            //zip4jUtil.emptyFile(jpgPath);
            // 接收压缩包 文件缓存到本地

            log.info("影像数据文件 ->" + decrypt + " " + multipartFiles.getOriginalFilename());

            File zipFile = new File(zipPath + multipartFiles.getOriginalFilename());
            try {
                //读取zipFile文件
                multipartFiles.transferTo(zipFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 解压
            zip4jUtil.unzip(zipPath + zipFile.getName(), filePath + study_uid);
            // 解压后的dcm文件
            List<File> fileList = fileExists.search(filePath + study_uid + "/", new ArrayList<>());
            //上传图片到PACS
            for (File JpgFile : fileList) {
                pacsRestTemplate.sendInstances(JpgFile);
                log.info("发送DICOM图像至Orthanc ->" + JpgFile.getName());
            }
        }
    }
}

然后在controller层中调用异步方式处理文件:
注意:在controller上添加 @EnableAsync 注解

package cn.stylefeng.guns.modular.api.controller;

import cn.stylefeng.guns.entity.Study;
import cn.stylefeng.guns.modular.api.async.AsyncDcm;
import cn.stylefeng.guns.modular.utils.AESUtil;
import cn.stylefeng.guns.modular.utils.FileExists;
import cn.stylefeng.guns.modular.utils.Zip4jUtil;
import cn.stylefeng.guns.sys.modular.system.entity.User;
import cn.stylefeng.guns.sys.modular.system.service.UserService;
import cn.stylefeng.guns.util.OrthancPacsRestTemplate;
import cn.stylefeng.roses.core.util.ToolUtil;
import cn.stylefeng.roses.kernel.model.response.ResponseData;
import lombok.extern.java.Log;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zc.workflow.form.handle.service.HandleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.*;

@Controller
@Log
@EnableAsync
@RequestMapping("/api")
public class HandleEquipController {

    @Autowired
    private HandleService handleService;

    @Autowired
    private UserService userService;

    @Autowired
    private AESUtil aesUtil;

    @Autowired
    private Zip4jUtil zip4jUtil;

    @Autowired
    private FileExists fileExists;

    @Value("${file.zipPath}")
    private String zipPath;

    @Value("${file.filePath}")
    private String filePath;

    @Value("${file.jpgPath}")
    private String jpgPath;

    @Autowired
    private AsyncDcm asyncDcm;


    /**
     * 接收影像设备检查结果:修改表单中图片影像、影像结果
     * @param enData 密文
     * @param multipartFiles  dcm文件压缩包
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, path="/acceptEquipmentResult")
    @ResponseBody
    public ResponseData acceptEquipmentResult(@RequestParam("enData") String enData,
                                              @RequestParam(value = "files", required = false) MultipartFile multipartFiles) {
    	
    	log.info("影像接收到密文 -> " + enData);
    	
        String allOrTaskForm = "allForm";
        String msg = "yes";
        // 解密
        String decrypt = aesUtil.decrypt(enData);
        
        log.info("影像数据解密 ->" + decrypt);
        
        // 解析为json数组
        JSONArray jsonArray = JSONArray.parseArray(decrypt);
        // 装入Study List集合
        List<Study> addList = jsonArray.toJavaList(Study.class);
        // 流程任务单据编号
        String processTaskCode = "";
        // 临床诊断
        String clinicalDiagnosis = "";
        // 用户uid (用于文件存储操作)
        String study_uid = "";
        // 操作用户
        String operateName = null;
        // 遍历集合 拿出数据
        for (Study study : addList) {
            processTaskCode = study.getPatient_id();
            clinicalDiagnosis = study.getFinding();
            if (study.getReporter() != null) {
                operateName = study.getReporter();
            }
            study_uid = study.getStudy_uid();
        }
        // 异步处理接收DCM文件
        asyncDcm.DCMDetailWith(multipartFiles, decrypt, study_uid);
        return ResponseData.success(result);
    }
}

最后在启动类上添加@EnableAsync 注解

测试

2022-07-22 15:29:52.121  INFO 4388 --- [scheduling-1] cn.zc.sport.medical.http.HuHttpUtil      : >>>>>>>>>> 发送完成,耗时:2822 ms <<<<<<<<<<

完美解决

总结

出现这个问题很多时候需要分析发出去请求之后等待的时间服务到底做了什么,如果确实都没发过去,那再调整超时时间,不然可以使用异步的方式缩短处理时间,还不行,推荐使用MQ异步消息队列。文章来源地址https://www.toymoban.com/news/detail-785332.html

到了这里,关于HttpClient报错cn.hutool.http.HttpException: Read timed out的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • cn.hutool.poi.excel.ExcelWriter 基础操作

    创建ExcelWriter 表格合并操作 行样式设置 写入列表数据 指定单元格式写入数据 结束 

    2024年02月13日
    浏览(48)
  • java.net.SocketTimeoutException: Read timed out,tcp连接心跳[TCP Keep-Alive],socket模拟http

     读超时con.setReadTimeout(3 * 60 * 60 * 1000);已设置为3小时。 日志 日志发现 等待了 3小时,抛出了异常 经过排查,是因为 后端防火墙,连接空闲20分钟,连接就会被丢弃。 解决办法是,使用 socket.setKeepAlive(true); 注意HttpURLConnection的connection.setRequestProperty(\\\"Connection\\\", \\\"keep-alive\\\");是不

    2024年02月07日
    浏览(35)
  • pip安装模块报错ReadTimeoutError: HTTPSConnectionPool(host=‘files.pythonhosted.org‘, port=443): Read timed

    今天在安装python模块时提示 ReadTimeoutError: HTTPSConnectionPool(host=‘files.pythonhosted.org’, port=443): Read timed out 具体报错如下: 处理方法 pip --default-timeout=100 install -U pygame 这使用pip安装超时,绝大多数原因是pip源在外国,所以国内使用,网络就算稳定,也有一定超时。–default-timeo

    2024年02月11日
    浏览(43)
  • 【Java-IO流】cn.hutool.core.io.IORuntimeException: IOException: Stream closed

    今天在项目中需要读取request请求中的body多次,当我直接去read的时候出现了问题; 报错如下: 产生的原因如下: httpServletRequest中的流只能读取一次的原因 想要多次读取request中body的内容,需要先存储一份,然后读取; 问了导师,有一个类可以多次读取body内容,因为他会将

    2024年02月11日
    浏览(53)
  • cn.hutool.core.exceptions.DependencyException:You need to add dependency of ‘poi-ooxml‘....>=4.12

    再继续往下看报错信息,可看到有 打开hutool 官网,在hutool官网搜索报错信息,如下,即可搜到以下解决方案:点击即可打开 从hutool 官网 可见造成这个问题的3个原因: 部分用户使用POI模块时会提示: 一般以下几个原因: 没有引入POI相关jar或引入版本太低 引入了多个版本的

    2024年02月15日
    浏览(45)
  • Read timed out; nested exception is java.net.SocketTimeoutException: Read timed out

    问题出现 问题处理 出问题的代码 延长的读取时间

    2024年02月03日
    浏览(50)
  • hive read time out

    hive-jdbc版本:2.3.9 报错信息如下: 问题定位:客户端的socket连接读超时,默认超时时间为30秒,需要在应用端增大读超时时间。 解决方案: 1)hiveConnection在使用socket连接时,设置了超时时间为30秒,超时时间较短,在运行稍微复杂点的SQL时,就会导致超时。如下图。    2) 

    2024年02月15日
    浏览(47)
  • 解决Read timed out和connect timed out的问题

    如果在新建Android项目时报错: Read timed out或者connect timed out 一定可以解决问题的办法如下: 第一步:打开项目下gradle中的第二个.properties文件,找到这个文件的下载路径,、一般卡顿是因为下载这个文件时网速较慢或者是因为在国外的原因。 第二步:按照文档中的路径,选

    2024年02月06日
    浏览(55)
  • 为HttpClient开启HTTP/2

    .Net Core在调用其他服务时,调用通常使用 HttpClient, 而HttpClient默认 使用HTTP/1.1 。     自 .NET Core 3.0 发布以来, .NET 开发人员可以使用 HttpClient 启用 HTTP/2 。   DefaultRequestVersion和DefaultVersionPolicy选项在HttpClient对象本身上可用。这些属性将应用于通过常规 HttpClient 方法(如Get

    2024年02月01日
    浏览(37)
  • 【安卓疑难杂症】:安卓安装、gradle下载、AndroidStudio报错:Connection timed out: connect If you are behind an HTTP proxy

              这几天在安装Android Studio的时候遇到了很多问题,特此做一个分享,希望对大家有所帮助,以下是我遇到的问题: Android版本不对,后换到我上周安装的版本才可以 gradle下载不了,很慢 AndroidStudio报错:Connection timed out: connect If you are behind an HTTP proxy SDK包 java安装 如

    2024年02月05日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包