当前位置: 首页 > 知识库问答 >
问题:

使用Spring REST模板,要么创建太多连接,要么速度太慢

陶瀚玥
2023-03-14

我有一个非常快速的RESTful服务。我正在本地主机上测试它。客户端正在使用Spring REST模板。我从一个天真的方法开始:

RestTemplate restTemplate = new RestTemplate(Collections.singletonList(new GsonHttpMessageConverter()));

Result result = restTemplate.postForObject(url, payload, Result.class);

当我提出很多这样的请求时,我得到了以下例外:

Caused by: org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:8080/myservice":No buffer space available (maximum connections reached?): connect; nested exception is java.net.SocketException: No buffer space available (maximum connections reached?): connect

这是由于连接未关闭且挂起在TIME_WAIT状态造成的。当临时端口耗尽时,异常开始发生。然后执行等待端口再次空闲。我看到了长时间Rest的最佳表现。我得到的速度几乎是我所需要的,但当然,这些时间等待连接并不好。在Linux(Ubuntu14)和Windows(7)上进行了测试,由于端口范围不同,在不同时间的测试结果相似。

为了解决这个问题,我尝试使用来自Apache Http Components库的带有HttpClientBuilder的HttpClient。

RestTemplate restTemplate = new RestTemplate(Collections.singletonList(new GsonHttpMessageConverter()));
HttpClient httpClient = HttpClientBuilder.create()
        .setMaxConnTotal(TOTAL)
        .setMaxConnPerRoute(PER_ROUTE)
        .build();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));

Result result = restTemplate.postForObject(url, payload, Result.class);

对于这个客户,我看不到任何例外。客户端现在只使用数量非常有限的临时端口。但无论我使用什么设置(总路线和每路线),我都无法获得所需的性能。

使用netstat命令,我发现与服务器的连接不多。我尝试将数字设置为数千,但客户似乎从未使用过那么多。

在不打开太多连接的情况下,我能做些什么来提高性能吗?

更新:我尝试将总连接数和每个路由连接数设置为5000和2500,但看起来客户端创建的连接数仍然不超过100(从netstat-n|wc-l判断)。REST服务是使用JAX-RS实现的,并在Jetty上运行。

更新2:我现在已经用一些内存设置调整了服务器,我获得了非常好的吞吐量。这种简单的方法仍然要快一点,但我认为这只是客户端池的一点开销。

共有1个答案

云宏儒
2023-03-14

实际上Spring Boot没有泄漏连接。您在这里看到的是Linux内核(以及每个主要操作系统)的标准行为。在一段时间内,所有从机器关闭的套接字都会进入TIME_WAIT状态。这是为了防止使用该临时端口的下一个套接字接收到实际上是为该端口上的前一个套接字准备的数据包。您所看到的两者之间的差异是每个连池方法的结果。

更具体地说,restemplate默认情况下不使用连接池。这意味着每次rest调用都会打开一个新的本地临时端口和与服务器的新连接。如果你的服务速度很快,它很快就会通过可用的本地端口范围。使用ApacheHttpClient,您可以利用连接池。这将阻止应用程序看到您描述的问题。然而,考虑到您的服务的响应速度比Linux内核从TIME_WAIT中取出套接字的速度更快,连接池将使您的客户端变得更慢,无论您做什么(如果它没有减慢任何速度,那么您将再次耗尽本地临时端口)。

虽然在Linux内核中启用TCP重用是可能的,但它可能会变得危险(数据包可能会被延迟,并且你可能会让临时端口接收到他们不理解的随机数据包,这可能会导致各种问题)。这里的解决方案是使用第二个示例中的连接池,使用足够多的连接池,以实现接近您期望的性能。

为了帮助您调整连接池,您需要调整MaxConnProuteMaxConntTotal参数maxConnPerRoute限制将连接到单个IP:端口对的连接数,maxTotal限制将打开的总连接数。在您的情况下,因为所有请求似乎都是在同一个位置发出的,所以您可以将它们设置为相同(高)值。

 类似资料:
  • 问题内容: 我有一个非常快速的RESTful服务。我正在本地主机上对其进行测试。客户端正在使用Spring REST模板。我从使用幼稚的方法开始: 当我提出许多此类请求时,出现以下异常: 这是由于未关闭连接并使其处于TIME_WAIT状态而引起的。当临时端口用尽时,该异常开始发生。然后执行将等待端口再次释放。我看到了长时间休息的最佳表现。我得到的速率几乎是我所需要的,但是这些TIME_WAIT连接

  • 本文向大家介绍webpack打包vue速度太慢怎么办?相关面试题,主要包含被问及webpack打包vue速度太慢怎么办?时的应答技巧和注意事项,需要的朋友参考一下 https://www.cnblogs.com/imwtr/p/9189670.html

  • 我知道这是一个常见的问题,但我觉得我已经试过了所有的解决方案,所以我不知道该怎么做了。 已安装Intel x86 HAXM 尝试在SDK管理器中重新安装仿真程序 尝试使用不同API级别的各种AVD 我不明白是怎么回事,在过去的两天里,我对这种情况感到非常沮丧,任何帮助或提示都将不胜感激!

  • 我使用MongoDbFactory用Java连接到mongodb。但mongo服务每小时至少抛出一次套接字异常。因此,我不得不重启mongodb服务来恢复操作。我认为这可能是因为从java到mongodb的连接未关闭,而且MongoDbFactory没有为我提供关闭连接的功能。如何确保在特定会话后关闭所有连接。 这是我正在使用的代码: } 和:

  • Cassandra要使用的连接URL是什么? jdbc:cassandra:root/root@:/

  • 每一个国家的都有其特殊国情,主要是原因是中国的网络太慢,及中国存在大量老旧的计算机,它们预装着window XP,IE浏览器最高只能升级到IE8, 出于这两方面的原因,我们需要一个体积更少,兼容性更好的React。并且之前facebook也闹过LICENSE问题,更是促进中国互联网公司决定自主研发框架,努力摆脱对外国框架的依赖。 对于我们公司而言,一个旅游公司, 在线上订火车票,飞机票, 景点门票