java实用型-高并发下RestTemplate的正确使用说明

 更新时间:2021年10月23日 11:57:59   作者:我们都爱松松吧  
这篇文章主要介绍了java实用型-高并发下RestTemplate的正确使用说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

前言

如果java项目里有调用第三方的http接口,我们可以使用RestTemplate去远程访问。也支持配置连接超时和响应超时,还可以配置各种长连接策略,也可以支持长连接预热,在高并发下,合理的配置使用能够有效提高第三方接口响应时间。

一、RestTemplate是什么?

RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。

二、如何使用

1.创建一个bean

以下代码配置比较简单,只设置了连接超时时间和响应超时时间

/**
 * restTemplate配置
 *
 * @author Songsong
 * @date 2020-08-17 15:09
 */
@Configuration
public class RestTemplateConfiguration {
    @Bean(name = "restTemplate")
    public RestTemplate restTemplate() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        //设置连接超时时间1s
        factory.setConnectTimeout(1000);
        //设置读取时间1s
        factory.setReadTimeout(1000);
        return new RestTemplate(factory);
    }
}

2.使用步骤

在需要使用的地方使用@Resource或者@Autowired注入进来

@Resource
private RestTemplate restTemplate;

然后我们平常调用第三方的接口是get方式和post方式,restTemplate提供getForEntity和postForEntity方法支持这两种方式,直接调用即可,源码分别如下:

getForEntity方法:

 public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientException {
        RequestCallback requestCallback = this.acceptHeaderRequestCallback(responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
        return (ResponseEntity)nonNull(this.execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
    }

postForEntity方法:

public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException {
        RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
        return (ResponseEntity)nonNull(this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables));
    }

源码中还有很多以上两种其他的重载方法,以上是作者平常项目中用的最多的一种,参数有url(第三方http链接)、request是请求所需的参数,responseType是返回类型里的泛型。

只需要解析返回的参数即可。

三、高并发下的RestTemplate使用

在平常的开发中,以上简单的配置可能就够用了,但是在高并发下,对接口响应时间要求很高,所以我们需要尽量的提高第三方接口响应时间。在RestTemplate中可以使用httpClient长连接,关于httpClient长连接的介绍我们可以参考:HTTPclient保持长连接

以下代码我们设置了长连接预热的功能,以及路由并发数:

@Slf4j
@Configuration
public class RestTemplateConfiguration {
    @Bean(name = "restTemplate")
    public RestTemplate restTemplate() {
       return getRestTemplate(3, "https://www.baidu.com/......");
    }
    private RestTemplate getRestTemplate(int maxTotal, String preHeatUrl) {
        HttpComponentsClientHttpRequestFactory httpRequestFactory = httpComponentsClientHttpRequestFactory(maxTotal);
        RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
        //解决首次预热耗时长
        if (StringUtils.isNotEmpty(preHeatUrl)) {
            try {
                restTemplate.postForEntity(preHeatUrl, "", String.class);
            } catch (Exception e) {
                log.error("preHeat url error:{}", e.getMessage());
            }
        }
        return restTemplate;
    }
    /**
     * ClientHttpRequestFactory接口的另一种实现方式(推荐使用),即:
     * HttpComponentsClientHttpRequestFactory:底层使用Httpclient连接池的方式创建Http连接请求
     *
     * @return
     */
    private HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory(int maxTotal) {
        //Httpclient连接池,长连接保持时间
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(1, TimeUnit.HOURS);
        //设置总连接数
        connectionManager.setMaxTotal(maxTotal);
        //设置同路由的并发数
        connectionManager.setDefaultMaxPerRoute(maxTotal);
        //设置header
        List<Header> headers = new ArrayList<Header>();
        headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.04"));
        headers.add(new BasicHeader("Accept-Encoding", "gzip, deflate"));
        headers.add(new BasicHeader("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3"));
        headers.add(new BasicHeader("Connection", "keep-alive"));
        //创建HttpClient
        HttpClient httpClient = HttpClientBuilder.create()
                .setConnectionManager(connectionManager)
                .setDefaultHeaders(headers)
                .setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)) //设置重试次数
                .setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy()) //设置保持长连接
                .build();
        //创建HttpComponentsClientHttpRequestFactory实例
        HttpComponentsClientHttpRequestFactory requestFactory =
                new HttpComponentsClientHttpRequestFactory(httpClient);
        //设置客户端和服务端建立连接的超时时间
        requestFactory.setConnectTimeout(10000);
        //设置客户端从服务端读取数据的超时时间
        requestFactory.setReadTimeout(5000);
        //设置从连接池获取连接的超时时间,不宜过长
        requestFactory.setConnectionRequestTimeout(2000);
        //缓冲请求数据,默认为true。通过POST或者PUT大量发送数据时,建议将此更改为false,以免耗尽内存
        requestFactory.setBufferRequestBody(false);
        return requestFactory;
    }

1.设置预热功能

我们可以看到,在getRestTemplate方法中,

return restTemplate;

之前先请求了一次,也就是说在需要使用第三方接口调用的service层注入的时候,提前先调用了一次,根据长连接的特性,一般第一次连接的时间较长,使用完之后,这个连接并不会马上回收掉,在一定的时间还是存活状态,所以在高并发下,经过预热后的接口响应时间会大幅提高。

2.合理设置maxtotal数量

我们可以看到以下代码

//设置总连接数
 connectionManager.setMaxTotal(maxTotal);

我们可以看到这一行,maxTotal是设置总连接数,这个设置需要根据接口的响应时间以及需要支持的QPS来设置,比如接口响应时间是100ms,需要支持的QPS为5000,也就是5000/s,那么一个长连接1s就是能够处理10个请求,那么总共需要maxTotal为500个,这个就是设置的大概数量,但是有时候QPS不是那么稳定,所以具体设置多少得视具体情况而定。

RestTemplate深度解析可以参考:RestTemplate深度解析

总结

以上就是关于RestTemplate的使用介绍,其实平常使用下还好,看不出来什么问题,但是一旦高并发情况下,预热和设置总连接数还有并发数以及其他的相关配置就显得尤为重要,具体的配置还是得经过实验才能得知,没有最好,只有更好,以上就是作者在高并发活动中的一些实际经历,希望可以帮助到你!!!如有错误或未考虑完全的地方,望不吝赐教,也希望大家多多支持脚本之家!

相关文章

  • C++内存管理看这一篇就够了

    C++内存管理看这一篇就够了

    这篇文章主要介绍了C/C++中的内存管理小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-08-08
  • 教你怎么用idea创建web项目

    教你怎么用idea创建web项目

    好多朋友在使用IDEA创建项目时,总会碰到一些小问题.现在我们就演示一下使用IDEA创建web项目的完整步骤吧.文中有非常详细的图文示例哦,,需要的朋友可以参考下
    2021-05-05
  • Java中关于内存泄漏出现的原因汇总及如何避免内存泄漏(超详细版)

    Java中关于内存泄漏出现的原因汇总及如何避免内存泄漏(超详细版)

    这篇文章主要介绍了Java中关于内存泄漏出现的原因汇总及如何避免内存泄漏(超详细版)的相关资料,需要的朋友可以参考下
    2016-09-09
  • 基于RabbitMQ的简单应用(详解)

    基于RabbitMQ的简单应用(详解)

    下面小编就为大家分享一篇基于RabbitMQ的简单应用(详解),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-11-11
  • 浅谈JAVA 类加载器

    浅谈JAVA 类加载器

    这篇文章主要介绍了JAVA 类加载器的的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • Java中JDBC事务与JTA分布式事务总结与区别

    Java中JDBC事务与JTA分布式事务总结与区别

    Java事务的类型有三种:JDBC事务、JTA(Java Transaction API)事务、容器事务,本文详细介绍了JDBC事务与JTA分布式事务,有需要的可以了解一下。
    2016-11-11
  • J2SE基础之JDK环境变量配置

    J2SE基础之JDK环境变量配置

    进行java开发,首先要安装jdk,安装了jdk后还要进行环境变量配置,下面我们就来详细探讨下这个问题。
    2016-05-05
  • JMETER用户变量作用域测试流程

    JMETER用户变量作用域测试流程

    这篇文章主要介绍了JMETER用户变量作用域测试流程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • Java获得一个数组的指定长度排列组合算法示例

    Java获得一个数组的指定长度排列组合算法示例

    这篇文章主要介绍了Java获得一个数组的指定长度排列组合算法,结合实例形式分析了java排列组合相关数组遍历、运算操作技巧,需要的朋友可以参考下
    2019-06-06
  • java实现同态加密算法的实例代码

    java实现同态加密算法的实例代码

    这篇文章主要给大家介绍了关于java实现同态加密算法的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12

最新评论