使用Spring REST模板,创建过多的连接或速度慢

我有一个非常快速的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状态而引起的。当临时端口用尽时,该异常开始发生。然后执行将等待端口再次释放。我看到了长时间休息的最佳表现。我得到的速率几乎是我所需要的,但是这些TIME_WAIT连接当然不是很好。在Linux(Ubuntu

14)和Windows(7)上进行了测试,由于端口范围不同,在不同时间的结果相似。

为了解决这个问题,我尝试将Apache Http Components库中的HttpClient与HttpClientBuilder一起使用。

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);

有了这个客户,我没有例外。客户端现在仅使用数量非常有限的临时端口。但是无论我使用什么设置(TOTAL和PER_ROUTE),都无法获得所需的性能。

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

有什么我可以做的以提高性能,而无需打开太多的连接?


更新:我尝试将总数和每条路由的连接数设置为5000和2500,但看起来客户端创建的总数不超过100(从判断netstat -n | wc

-l)。REST服务是使用JAX-RS实现的,并在Jetty上运行。

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

回答:

实际上,Spring

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

更具体地说,默认情况下RestTemplate

使用连接池。这意味着每个rest调用都会打开一个新的本地临时端口和一个到服务器的新连接。如果您的服务速度非常快,它将立即在可用的本地端口范围内爆炸。使用Apache

HttpClient,您可以利用连接池。这将防止您的应用程序看到您描述的问题。但是,鉴于您的服务能够比Linux内核从中取出套接字更快地做出响应TIME_WAIT,因此无论您做什么,连接池都会使您的客户端变慢(如果它没有使任何事情变慢,那么您就用光了本地临时端口)。

尽管可以在Linux内核中启用TCP重用,但这样做可能会很危险(数据包可能会延迟,并且临时端口可能会收到他们不了解的随机数据包,这可能会导致各种问题)。这里的解决方案是使用连接池,就像在第二个示例中一样,使用足够大的数量来达到接近您想要的性能。

为了帮助您调整连接池,您需要调整maxConnPerRoutemaxConnTotal参数。maxConnPerRoute限制将对单个IP:Port对maxTotal建立的连接数,并限制将永远打开的总连接数。在您的情况下,由于似乎所有请求都发送到同一位置,因此可以将它们设置为相同(较高)值。

以上是 使用Spring REST模板,创建过多的连接或速度慢 的全部内容, 来源链接: utcz.com/qa/422043.html

回到顶部