百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

踩坑日记(九):挖一个 RestTemplate 高并发的坑

toyiye 2024-08-25 15:53 9 浏览 0 评论

背景

最近上线了一个功能,需要调用第三方的一个 API 获取相关业务数据,交互关系如下:

业务非常的单纯,开发时看到项目中采用的是 RestTemplate 做服务间的数据交互,那么这个功能也就继续沿用。

经过功能测试、发布上线。。。。

接着就陆陆续续收到了一些延迟预警,并且用户也反映客户端会偶尔出现卡顿现象。

疯狂找问题中。。。。

loading。。。

问题排查

1、压测功能接口

很容易就复现了这个问题,经过检查代码没有做很多的业务逻辑,但是平均响应时间和最大响应时间都很不理想。

接着联系第三方工程师一起监控一下服务状态,

2、压测第三方接口

经过和第三方厂商工程师沟通,配合一起压测,第三方结果如下:

第三方API 非常稳定,30 ~ 50 毫秒就能返回结果。

3、排查服务器网络

肯定是服务间交互的网络问题,然后在服务器上直接搭建 JMeter 压测环境,得到结果和第三方提供的相差不大,稳定在 70 毫秒(约20毫秒的网络损耗)。

从这里基本定位到是服务调用方的问题了,进一步可以缩小到是 RestTemplate 。

问题分析

查看了 RestTemplate 实现原理发现初始化的时候用了 HttpComponentsClientHttpRequestFactory,目的是为了配置 RestTemplate 的超时配置。

源码如下:

从上图可以看到 RestTemplate 底层默认用的是 HttpClient,然后他的一个构建工厂HttpClientBuilder有一个属性是systemProperties。再看下面的源码:

如果 systemProperties 这个属性为 【true】的时候,HttpClient 保持长连接了,并且接下来会使用默认一个重用策略 DefaultClientConnectionReuseStrategy.INSTANCE;

并且初始化最大连接数是 5 ......

问题

使用默认的初始化 HttpComponentsClientHttpRequestFactory 的时候,HttpClient 的长连接会生效,如果出现调用通的情况,长连接在超时时间内会一直保持着连接,并且会复用上一次的连接信息。

解决方案

要解决这个问题也比较简单,只需要在初始化 HttpComponentsClientHttpRequestFactory 的时候,传入自定义的 HttpClient 来实例HttpComponentsClientHttpRequestFactory,这样就不会使用默认的HttpClient的长连接。

pom.xml 引入 httpclient 和 httpcore 依赖

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <version>4.4.14</version>
</dependency>

增加 RestTemplateConfig.java

import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
	@Bean
	public RestTemplate restTemplate() {
		return new RestTemplate(httpRequestFactory());
	}


	@Bean
	public ClientHttpRequestFactory httpRequestFactory() {
		return new HttpComponentsClientHttpRequestFactory(httpClient());
	}


	@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(800);

		// 路由是对maxTotal的细分
		connectionManager.setDefaultMaxPerRoute(100);
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(5000)  // 返回数据的超时时间
				.setConnectTimeout(3000) // 连接上服务器的超时时间
				.setConnectionRequestTimeout(1000) // 从连接池中获取连接的超时时间
				.build();
		return HttpClientBuilder.create()
				.setDefaultRequestConfig(requestConfig)
				.setConnectionManager(connectionManager)
				.build();
	}
}

代码中也一并配置了 HttpClient 最大连接数以及同路由并发数,增加高并发的时候 RestTemplate的性能!

总结

在和第三方交互的时候要考虑到除业务之外细节,有条件的情况下一定要做压力测试,这样对自己的代码有一个更加清晰的认识。特别是用一些框架默认配置,要大致的看一下具体的实现方式,特别是需要知道是否需要自定义配置,自己的配置是否齐全。

相关推荐

# Python 3 # Python 3字典Dictionary(1)

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中,格式如...

Python第八课:数据类型中的字典及其函数与方法

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值...

Python中字典详解(python 中字典)

字典是Python中使用键进行索引的重要数据结构。它们是无序的项序列(键值对),这意味着顺序不被保留。键是不可变的。与列表一样,字典的值可以保存异构数据,即整数、浮点、字符串、NaN、布尔值、列表、数...

Python3.9又更新了:dict内置新功能,正式版十月见面

机器之心报道参与:一鸣、JaminPython3.8的热乎劲还没过去,Python就又双叒叕要更新了。近日,3.9版本的第四个alpha版已经开源。从文档中,我们可以看到官方透露的对dic...

Python3 基本数据类型详解(python三种基本数据类型)

文章来源:加米谷大数据Python中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。在Python中,变量就是变量,它没有类型,我们所说的"类型"是变...

一文掌握Python的字典(python字典用法大全)

字典是Python中最强大、最灵活的内置数据结构之一。它们允许存储键值对,从而实现高效的数据检索、操作和组织。本文深入探讨了字典,涵盖了它们的创建、操作和高级用法,以帮助中级Python开发...

超级完整|Python字典详解(python字典的方法或操作)

一、字典概述01字典的格式Python字典是一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。字典的每个键值key=>value对用冒号:分割,每个对之间用逗号,...

Python3.9版本新特性:字典合并操作的详细解读

处于测试阶段的Python3.9版本中有一个新特性:我们在使用Python字典时,将能够编写出更可读、更紧凑的代码啦!Python版本你现在使用哪种版本的Python?3.7分?3.5分?还是2.7...

python 自学,字典3(一些例子)(python字典有哪些基本操作)

例子11;如何批量复制字典里的内容2;如何批量修改字典的内容3;如何批量修改字典里某些指定的内容...

Python3.9中的字典合并和更新,几乎影响了所有Python程序员

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

Python3大字典:《Python3自学速查手册.pdf》限时下载中

最近有人会想了,2022了,想学Python晚不晚,学习python有前途吗?IT行业行业薪资高,发展前景好,是很多求职群里严重的香饽饽,而要进入这个高薪行业,也不是那么轻而易举的,拿信工专业的大学生...

python学习——字典(python字典基本操作)

字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包含的元素个数不限,值...

324页清华教授撰写【Python 3 菜鸟查询手册】火了,小白入门字典

如何入门学习python...

Python3.9中的字典合并和更新,了解一下

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

python3基础之字典(python中字典的基本操作)

字典和列表一样,也是python内置的一种数据结构。字典的结构如下图:列表用中括号[]把元素包起来,而字典是用大括号{}把元素包起来,只不过字典的每一个元素都包含键和值两部分。键和值是一一对应的...

取消回复欢迎 发表评论:

请填写验证码