HttpClient,RestTemplate超时设置

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

最近在使用RestTemplate的时候发现一个坑,就是某一次发送请求的时候突然卡住不动了,而且没有任何报错提示,重启下服务器就好,可见是因为某些特殊原因导致的,在网上找了下资料发现是因为没有设置超时时间,默认超时时间为永久,就想做一些试验复现下这个bug.

HttpClient试验

不设置HttpClient超时时间,看看发送请求的过程中如果目标服务突然挂掉会怎么样

public class HttpTimeoutTest {
    @Test
    public void testHttpClient() {
        String url = "http://localhost:8081/httpTest/testSleep";
        Map params = new HashMap();
        params.put("time", 30);
        String result = doGet(url, params, null);
        System.out.println(result);
    }

    private static CloseableHttpClient buildClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        //设置连接超时时间
        RequestConfig.Builder builder = RequestConfig.custom();
        /*builder.setConnectTimeout(60 * 1000);
        builder.setSocketTimeout(180 * 1000);*/
        RequestConfig requestConfig = builder.build();
        SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
            public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                return true;
            }
        }).build();
        SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext,
                NoopHostnameVerifier.INSTANCE);
        CloseableHttpClient httpclient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setSSLSocketFactory(sslSocketFactory).build();
        return httpclient;
    }

    public static String doGet(String url, Map<String, Object> params, Map<String, String> headersMap) {
        String result = null;
        CloseableHttpClient httpClient = null;
        try {
            httpClient = buildClient();
            String apiUrl = url;
            if (null != params && params.size() > 0) {
                StringBuffer param = new StringBuffer();
                int i = 0;
                for (String key : params.keySet()) {
                    if (i == 0)
                        param.append("?");
                    else
                        param.append("&");
                    param.append(key).append("=").append(params.get(key));
                    i++;
                }
                apiUrl += param;
            }

            HttpGet httpGet = new HttpGet(apiUrl);
            if (null != headersMap && headersMap.size() > 0) {
                for (Map.Entry<String, String> entry : headersMap.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    httpGet.addHeader(new BasicHeader(key, value));
                }
            }
            CloseableHttpResponse response = httpClient.execute(httpGet);
            try {
                HttpEntity entity = response.getEntity();
                if (null != entity) {
                    result = EntityUtils.toString(entity, "utf-8");
                }
            } finally {
                response.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IoUtil.close(httpClient);
        }
        return result;
    }
}

发现抛NoHttpResponseException了,目标服务突然断开不会造成卡死

org.apache.http.NoHttpResponseException: The target server failed to respond
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:141)
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
    at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
    at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163)
    at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:157)

这是为什么呢?

我们知道,建立tcp连接需要三次握手,断开连接需要四次挥手,当进程主动close掉连接时,请求方是可以正常接收到,如果是进程突然挂掉呢?那操作系统就会去关闭连接,所以请求方还是能知道

那如果是服务器突然断网或者服务器挂掉了呢?这时服务器没法主动断开连接,请求方就会一直等待,这时就会造成卡死现象。

我们给HttpClient设置超时时间,再试试

builder.setConnectTimeout(5 * 1000); // 建立三次握手的超时时间
builder.setSocketTimeout(40 * 1000); // 没收到服务器数据的超时时间

可以发现超过40s还没返回,就会抛SocketTimeoutException

java.net.SocketTimeoutException: Read timed out
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:170)

connectTimeout是建立连接的时间,如果服务器没挂,进程挂了,则3s就会报Connection refused: connect,否则就要20s,所以最好也设置下

RestTemplate超时时间

接下去我们用RestTemplate重复以上实验,发现会有同样的问题,这是就要设置超时时间了文章来源地址https://www.toymoban.com/news/detail-451409.html

    @Test
    public void testRestTemplate() {
        RestTemplate restTemplate = restTemplate();
        String url = "http://localhost:8081/httpTest/testSleep?time=30";
        ResponseEntity responseEntity = restTemplate.getForEntity(url, String.class);
        System.out.println(responseEntity.getBody());
    }

    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setRequestFactory(clientHttpRequestFactory());
        restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
        return restTemplate;
    }

    public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() {
        try {
            HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new org.apache.http.ssl.TrustStrategy() {
                public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                    return true;
                }
            }).build();
            httpClientBuilder.setSSLContext(sslContext);
            HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.getSocketFactory())
                    .register("https", sslConnectionSocketFactory).build();// 注册http和https请求
            // 开始设置连接池
            PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            poolingHttpClientConnectionManager.setMaxTotal(500); // 最大连接数500
            poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100); // 同路由并发数100
            httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
            HttpClient httpClient = httpClientBuilder.build();
            HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); // httpClient连接配置
            clientHttpRequestFactory.setConnectTimeout(20 * 1000);              // 连接超时
            clientHttpRequestFactory.setReadTimeout(30 * 1000);                 // 数据读取超时时间
            clientHttpRequestFactory.setConnectionRequestTimeout(20 * 1000);    // 连接不够用的等待时间
            return clientHttpRequestFactory;
        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
            e.printStackTrace();
        }
        return null;
    }

到了这里,关于HttpClient,RestTemplate超时设置的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • .NET 5 以后的 HttpClient 超时问题

    起因是朋友在使用深信服的 Easy Connect 连接到内网之后,使用 HttpClient 访问对应内网的 API 站点均返回 System.Net.Sockets.SocketException (10060) 异常。但使用其他语言的原生 HTTP 库,比如 Golang / Python / Java 都可以正常访问,因此怀疑是 HttpClient 的问题。 经过搜索得知,这是存在于 .

    2024年02月08日
    浏览(81)
  • 【Java万花筒】解码Java网络通讯谜团:对比Apache HttpClient、OkHttp、Feign、RestTemplate、Retrofit

    在当今互联网时代,Java开发者常常需要处理与各种RESTful服务的通信。本文旨在深入比较Java中几个主流的网络请求库,包括Apache HttpClient、OkHttp、Feign、RestTemplate、Retrofit。通过全面的介绍和示例代码,读者将能够了解它们的特点、优势以及如何在实际项目中使用。 欢迎订阅专

    2024年01月25日
    浏览(46)
  • java中http请求之restTemplate配置超时时间(亲测有用!)

    问题: http请求发起后接收不到返回数据!!!【测试环境没出问题,发到正式环境就有问题】 项目中通过restTemplate发起请求: 打印日志1内容为: http请求入参:{data=[{ productStatus=10,skuCode=null}], messageId=ewpfpr1t6ey5r6qj0su0w1h6rt73hr,token=vgvU5EJKuZbuHii7WH6pTINp40ZRicaqLz4dq5P7L6pDzWir8EEGZhCKPuc

    2024年02月11日
    浏览(39)
  • 使用RestTemplate访问https实现SSL请求操作,设置TLS版本

    注意:服务端TLS版本要和客户端工具类中定义的一致, 当支持的是列表时,能够与不同版本的客户端进行通信,在握手期间,TLS会选择两者都支持的最高的版本 javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure解决方案 方法升级JDK版本 全局设置优先级 代码里面的设置

    2024年02月01日
    浏览(38)
  • ChatGPT之后,下个AIGC杀手级应用已近在眼前

    鱼羊 发自 凹非寺 量子位 | 公众号 QbitAI 大模型模式,正在新一波AIGC的浪潮里被再度验证。 从AI画画的出圈,到现如今ChatGPT的火爆,面向大众的爆款产品接口背后,无不是大模型技术的突破创新。 而当这种“大力出奇迹”的技术路径价值愈发凸显,行业内外也不禁好奇:

    2024年02月10日
    浏览(45)
  • CSDN博客批量查询质量分https://yma16.inscode.cc/请求超时问题(设置postman超时时间)(接口提供者设置了nginx超时时间)

    https://yma16.inscode.cc/ 查询别人的一下子就返回了,查询我自己的,1分钟还不返回,然后就显示超时了。。 一开始我还以为是这个开源项目本身的问题,设置了请求超时时间,我还给它改了超时时间,后来发现不是的。。。 本来是100000的,我给改成1000000了,我对js代码不熟,

    2024年02月12日
    浏览(51)
  • UDP接收设置阻塞超时

    基于udp的socket通信时,linux系统调用recvfrom函数。 函数功能如下: 从套接字上接收一个消息。 recvfrom :可同时应用于面向连接(TCP)的和无连接(UDP)的套接字。 recv:一般只用在面向连接(TCP)的套接字,几乎等同于recvfrom,只要将recvfrom的第五个参数设置NULL。 存在的问题

    2024年02月16日
    浏览(35)
  • Nginx超时设置

    nginx中有些超时设置,本文汇总了nginx中几个超时设置 Nginx 中的超时设置包括: “client_body_timeout”:设置客户端向服务器发送请求体的超时时间,单位为秒。 “client_header_timeout”:设置客户端向服务器发送请求头的超时时间,单位为秒。 “send_timeout”:设置服务器向客户端

    2024年02月08日
    浏览(48)
  • 设置RabbitMQ超时时间

    RabbitMQ默认的超时时间是30分钟,在消息消费超过30分钟后,rabbitMQ会发生错误,导致整个channel被销毁,无法继续消费 在RabbitMQ安装的终端执行 命令,将超时时间延长。 使用 可以查看设置的超时值。 值得注意的是,这个事临时更改,永久更改需要进入 rabbitmq.con f 文件里修改

    2024年02月04日
    浏览(38)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包