• springboot RestTemplate优化 http 池化


    前言

    • 为何要用http连接池那?因为使用它我们可以得到以下好处:
      • 因为使用它可以有效降低延迟和系统开销。如果不采用连接池,每当我们发起http请求时,都需要重新发起Tcp三次握手建立链接,请求结束时还需要四次挥手释放链接。而链接的建立和释放是有时间和系统开销的。另外每次发起请求时,需要分配一个端口号,请求完毕后在进行回收。
      • 使用链接池则可以复用已经建立好的链接,一定程度的避免了建立和释放链接的时间开销。

    http通信之三次握手

    • 为了对每次发送的数据量进行跟踪与协商,确保数据段的发送和接收同步,根据所接收到的数据量而确认数据发送、接收完毕后何时撤消联系,并建立虚连接。

    • TCP在发送新的数据之前,以特定的顺序将数据包的序号,并需要这些包传送给目标机之后的确认消息。TCP总是用来发送大批量的数据。当应用程序在收到数据后要做出确认时也要用到TCP。

    在这里插入图片描述

    此次优化解决问题

    • 异常 Caused by: java.io.IOException: Broken pipe
      • 异常原因分析
        • 服务端向前端socket连接管道写返回数据时 链接(pipe)却断开了
          • 从应用角度分析,这是因为客户端等待返回超时了,主动断开了与服务端链接
          • 连接数设置太小,并发量增加后,造成大量请求排队等待
          • 网络延迟,是否有丢包
          • 内存是否足够多支持对应的并发量

    okhttp 实现池化

    springboot 项目导入依赖okhttp依赖
            <dependency>
                <groupId>com.squareup.okhttp3groupId>
                <artifactId>okhttpartifactId>
                <version>4.10.0version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    配置 RestTemplateConfig
    
    /**
     * 其他模板配置
     *
     * @author 13208
     * @date 2022/11/16
     */
    @Configuration
    public class RestTemplateConfig {
    
        @Bean
        public RestTemplate restTemplate(ClientHttpRequestFactory requestFactory) {
            return new RestTemplate(requestFactory);
        }
    
        @Bean
        public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
            OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory(okHttpClient());
            factory.setReadTimeout(10000);
            factory.setConnectTimeout(10000);
            return factory;
        }
        @Bean
        public OkHttpClient okHttpClient() {
            // 设置连接池参数,最大空闲连接数200,空闲连接存活时间10s
            ConnectionPool connectionPool = new ConnectionPool(200, 10, TimeUnit.SECONDS);
            OkHttpClient okHttpClient = new OkHttpClient.Builder().
                    retryOnConnectionFailure(false)
                    .connectionPool(connectionPool)
                    .connectTimeout(3, TimeUnit.SECONDS)
                    .readTimeout(3, TimeUnit.SECONDS)
                    .writeTimeout(3, TimeUnit.SECONDS).build();
            return okHttpClient;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    httpClient 实现池化

    springboot 项目导入依赖httpClient 依赖
    		<dependency>
    		    <groupId>org.apache.httpcomponentsgroupId>
    		    <artifactId>httpclientartifactId>
    		    <version>4.5.13version>
    		dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    配置 RestTemplateConfig
    
    /**
     * 其他模板配置
     *
     * @author 13208
     * @date 2022/11/16
     */
    @Configuration
    public class RestTemplateConfig {
    
        @Bean
        public RestTemplate restTemplate(ClientHttpRequestFactory requestFactory) {
            return new RestTemplate(requestFactory);
        }
    
        @Bean
        public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
            HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
            factory.setReadTimeout(10000);
            factory.setConnectTimeout(10000);
            factory.setHttpClient(httpClient());
            return factory;
        }
    
        /**
         * @return
         */
        @Bean
        public HttpClient httpClient() {
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.getSocketFactory())
                    .register("https", SSLConnectionSocketFactory.getSocketFactory())
                    .build();
    
            PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
    
            //设置整个连接池最大连接数
            connectionManager.setMaxTotal(500);
    
            //MaxPerRoute路由是对maxTotal的细分,每个主机的并发,这里route指的是域名
            connectionManager.setDefaultMaxPerRoute(200);
            RequestConfig requestConfig = RequestConfig.custom()
                    //返回数据的超时时间
                    .setSocketTimeout(20000)
                    //连接上服务器的超时时间
                    .setConnectTimeout(10000)
                    //从连接池中获取连接的超时时间
                    .setConnectionRequestTimeout(1000)
                    .build();
    
            return HttpClientBuilder.create()
                    .setDefaultRequestConfig(requestConfig)
                    .setConnectionManager(connectionManager)
                    .build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
  • 相关阅读:
    执行可执行程序时遇到error while loading shared libraries错误解决
    java计算机毕业设计动漫论坛系统源码+mysql数据库+系统+lw文档+部署
    Spring Boot 在进行依赖注入时,使用了反射机制,类加载器-启动类拓展类-应用类加载器
    基于学习的决策树
    如何在OpenWRT上配置SFTP远程文件传输
    基于Cortex-M的RTOS上下文切换详解及FreeRTOS实例
    java基于Springboot+vue+nodejs的高校二手闲置商品交易求购平台系统 element
    人机融合有助于解决P-NP问题的理解与解决
    31_ADC基本原理及单次采集实验
    Hive开窗函数根据特定条件取上一条最接近时间的数据(根据条件取窗口函数的值)
  • 原文地址:https://blog.csdn.net/laow1314/article/details/127895635