使用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,但看起来客户端创建的连接数仍不超过一百个(从判断)。REST 服务是使用 JAX-RS 实现的,并在 Jetty 上运行。netstat -n | wc -l
UPDATE2:我现在已经使用一些内存设置调整了服务器,并且我获得了非常好的吞吐量。天真的方法仍然有点快,但我认为这只是客户端池的一点开销。