首页 > 其他分享 >RestTemplate连续读取两个不同文件时报错Read timed out

RestTemplate连续读取两个不同文件时报错Read timed out

时间:2023-12-01 11:45:52浏览次数:53  
标签:读取 Read RestTemplate MediaType add mediaTypes timed converter

在项目上负责对接一些三方接口,鉴于之前的经验,选择使用RestTemplate来实现各种http请求,以及文件的读取。

首先写了RestTemplate的配置类来配置基础信息,代码如下:

@Configuration
@ConditionalOnClass(value = {RestTemplate.class, HttpClient.class})
public class RestTemplateConfig {

    @Value("${remote.maxTotalConnect:1000}")
    private int maxTotalConnect; //连接池的最大连接数1000
    @Value("${remote.maxConnectPerRoute:100}")
    private int maxConnectPerRoute; //单个主机的最大连接数200
    @Value("${remote.connectTimeout:2000}")
    private int connectTimeout; //连接超时默认2s
    @Value("${remote.readTimeout:30000}")
    private int readTimeout; //读取超时默认30s
    @Value("${remote.readTimeout:10000}")
    private int connectionRequestTimeout;   // 从连接池获取连接的超时时间默认10s

    //创建HTTP客户端工厂
    private ClientHttpRequestFactory createFactory() {
        if (this.maxTotalConnect <= 0) {
            SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
            factory.setConnectTimeout(this.connectTimeout);
            factory.setReadTimeout(this.readTimeout);
            return factory;
        }
        HttpClient httpClient = HttpClientBuilder.create().setMaxConnTotal(this.maxTotalConnect)
                .setMaxConnPerRoute(this.maxConnectPerRoute).setConnectionTimeToLive(30, TimeUnit.MINUTES).build();
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(
                httpClient);
        factory.setConnectTimeout(this.connectTimeout);
        factory.setReadTimeout(this.readTimeout);
        factory.setConnectionRequestTimeout(connectionRequestTimeout);
        return factory;
    }

    //初始化RestTemplate,并加入spring的Bean工厂,由spring统一管理
    @Bean
    @ConditionalOnMissingBean(RestTemplate.class)
    public RestTemplate getRestTemplate() {
        RestTemplate restTemplate = new RestTemplate(this.createFactory());
        //换上fastjson
        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        Iterator<HttpMessageConverter<?>> iterator = messageConverters.iterator();
        while (iterator.hasNext()) {
            HttpMessageConverter<?> converter = iterator.next();
            //原有的String是ISO-8859-1编码 去掉
            if (converter instanceof StringHttpMessageConverter) {
                iterator.remove();
            }
            //由于系统中默认有jackson 在转换json时自动会启用  但是我们不想使用它 可以直接移除
            if (converter instanceof GsonHttpMessageConverter || converter instanceof MappingJackson2HttpMessageConverter) {
                iterator.remove();
            }
        }
        messageConverters.add(new StringHttpMessageConverter(Charset.forName("utf-8")));
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        /** 设置支持的MediaType**/
        List<MediaType> mediaTypes = new ArrayList<>();
        mediaTypes.add(MediaType.APPLICATION_JSON);
        mediaTypes.add(MediaType.APPLICATION_ATOM_XML);
        mediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
        mediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
        mediaTypes.add(MediaType.APPLICATION_PDF);
        mediaTypes.add(MediaType.APPLICATION_RSS_XML);
        mediaTypes.add(MediaType.APPLICATION_XHTML_XML);
        mediaTypes.add(MediaType.APPLICATION_XML);
        mediaTypes.add(MediaType.IMAGE_GIF);
        mediaTypes.add(MediaType.IMAGE_JPEG);
        mediaTypes.add(MediaType.IMAGE_PNG);
        mediaTypes.add(MediaType.TEXT_EVENT_STREAM);
        mediaTypes.add(MediaType.TEXT_HTML);
        mediaTypes.add(MediaType.TEXT_MARKDOWN);
        mediaTypes.add(MediaType.TEXT_PLAIN);
        mediaTypes.add(MediaType.TEXT_XML);
        converter.setSupportedMediaTypes(mediaTypes);
//      设置默认的字符集
        converter.setDefaultCharset(Charset.forName("UTF-8"));
//      设置默认的时间格式
        JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteDateUseDateFormat);
//       设置序列化方式
        fastJsonConfig.setSerializerFeatures(
                //List字段如果为null,输出为[],而非null
                SerializerFeature.WriteNullListAsEmpty,
                //是否输出值为null的字段
                SerializerFeature.WriteMapNullValue,
                //字符类型字段如果为null,输出为”“,而非null
                SerializerFeature.WriteNullStringAsEmpty,
                //消除对同一对象循环引用的问题
                SerializerFeature.DisableCircularReferenceDetect);
        converter.setFastJsonConfig(fastJsonConfig);
        messageConverters.add(converter);
        return restTemplate;
    }

}

  然后在项目中用@Resource  RestTemplate 使用就可以了;代码完成后打包启用一切正常。在测试环境运行一周后突然开始报错,测试反馈系统一直timed out,整个业务流程被阻断了

 查看日志,确如测试同事所说,当天调用该方法的请求都出现了这个问题。这就尴尬了,之前也这么写的,为啥现在报错了,而且前一天还是正常的。一直没想通,改用httpClient方式,发现还是timed out。再看代码,是系统要连续读取两张照片,第一张读取时是没问题的,在读取第二张时,系统明显感觉发送完请求就假死了,一直到连接超时。

 鉴于图片用两种读取方式都能读到第一张,所以想着用每种方式读取一张,看能不能完成本次需求,代码修改后,再次测试,系统正常跑完流程,未再报错。但是为什么用RestTemplate连续读取两次报错,一直不理解。直到查资料RestTemplate还有个connectionRequestTimeout时间设置。源码如下:

 用翻译软件翻译结果如下:

        设置请求连接时使用的超时(以毫秒为单位) 使用底层的{@link RequestConfig}从连接管理器获取。 超时值0指定无限超时。 其他属性可以通过指定 {@link RequestConfig}在自定义{@link HttpClient}上的实例。 请求连接的超时值,以毫秒为单位。

原来是RestTemplate,连接池关闭获取不到连接就报readtimeout异常,随后在RestTemplateConfiguration设置上connectionRequestTimeout时间10s,再次测试OK。与通过两种不同方式读取结果一致,都能完成业务正常流水。至此问题解决!

标签:读取,Read,RestTemplate,MediaType,add,mediaTypes,timed,converter
From: https://www.cnblogs.com/yandugu/p/17869369.html

相关文章

  • ESXi 主机的 CPU Ready值的范围
    ESXi主机的CPUReady值是指虚拟机在获取CPU资源之前等待的时间。CPUReady值越高,表示虚拟机在等待CPU资源的时间越长,性能越差。根据VMware官方的建议,ESXi主机的CPUReady值的正常范围如下:**0<%RDY<=5%:**此为正常区间,表示虚拟机的性能不会受到明显影响。**5%......
  • 17-有参转录组实战3-计算readcount和TPM表达量
     #本教程部分文件,来源B站15天入门生物信息教程“https://www.bilibili.com/video/BV1K44y1B7Dg/?spm_id_from=333.337.search-card.all.click&vd_source=19eea84b7c1e944fd3c6b3ccca066ade”#1,先将毛果杨的GFF格式的注释文件转换为GTF格式:condainstallgffreadgffread......
  • ThreadPoolExecutor线程池内部处理浅析
    我们知道如果程序中并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束时,会因为频繁创建线程而大大降低系统的效率,因此出现了线程池的使用方式,它可以提前创建好线程来执行任务。本文主要通过java的ThreadPoolExecutor来查看线程池的内部处理过程。1ThreadPoolExec......
  • C++ 11 关键字:thread_local
    thread_local是C++11新引入的一种存储类型,它会影响变量的存储周期。C++中有4种存储周期:automaticstaticdynamicthread有且只有thread_local关键字修饰的变量具有线程(thread)周期,这些变量在线程开始的时候被生成,在线程结束的时候被销毁,并且每一个线程都拥有一个独......
  • Requirement already satisfied解决办法
    python正常安装其他库后。pipinstallxlwings提示以下信息。Requirementalreadysatisfied:xlwingsinc:\users\zheng\appdata\local\programs\python\python38\lib\site-packages(0.30.12)Requirementalreadysatisfied:pywin32>=224inc:\users\zheng\appdat......
  • TypeError: Cannot read properties of undefined (reading '$modal')
    原代码:handleFinish(row){this.$modal.confirm('确认录取学生编号为"'+row.stuCode+'"的成绩?').then(function(){finishStudentScore({id:row.id}).then((response)=>{if(response.code==......
  • 处理挖矿病毒kthreaddk的过程
    问题描述发现服务器的CPU和内存占用非常高,然后看了一下发现有几个异常的程序PIDUSERPRNIVIRTRESSHRS%CPU%MEMTIME+COMMAND12043root......
  • idea报错:XXX already exist in project. Please, specify another name.
    问题:idea报错:XXXalreadyexistinproject.Please,specifyanothername.并且左侧目录中并没有看见同名存在文件解决方法:1.打开File->ProjectStructure2.点击Modules->找到报错说存在的模块->点击减号删除->Apply->OK反思问题为什么存在应该是我在系统文件夹中之......
  • npm学习(九)之README.md文件
      包括文档(readme.md)npm建议您包含一个readme文件来记录您的包。自述文件必须有文件名readme.md。文件扩展名.md表示该文件是一个标记(markdown)文件。当有人发现您的包时,该文件将出现在npm网站上。在开始之前,请查看一些包页面,了解可以添加到readme文件中的信息,并了解为......
  • thread
    thread之前未解决的问题tp是什么?thethreadpointer,whichxv6usestoholdthiscore'shartid(corenumber),theindexintocpus[],实际上是存放着hartid的寄存器hartid是什么?运行当前代码硬件线程(hart)的ID。对软件层面来说,就是一个独立的处理器。但是实际上也有可能......