如何确定setMaxTotal和setDefaultMaxPerRoute的最佳设置?

时间:2015-06-22 20:54:39

标签: java spring connection-pooling apache-httpclient-4.x resttemplate

我有一个RestService在三个数据中心的45台不同的机器上运行(每个数据中心有15台)。我有一个客户端库,使用RestTemplate来调用这些机器,具体取决于调用的来源。如果呼叫来自DC1,那么我的图书馆将在DC1中呼叫我的休息服务,对其他人也是如此。

我的客户端库在三个数据中心的不同计算机上运行(不在同一台45台计算机上)。

我正在使用RestTemplate HttpComponentsClientHttpRequestFactory,如下所示:

public class DataProcess {

    private RestTemplate restTemplate = new RestTemplate();
    private ExecutorService service = Executors.newFixedThreadPool(15);

    // singleton class so only one instance
    public DataProcess() {
        restTemplate.setRequestFactory(clientHttpRequestFactory());
    }

    public DataResponse getData(DataKey key) {
        // do some stuff here which will internally call our RestService
        // by using DataKey object and using RestTemplate which I am making below
    }   

    private ClientHttpRequestFactory clientHttpRequestFactory() {
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(1000).setConnectTimeout(1000)
                .setSocketTimeout(1000).setStaleConnectionCheckEnabled(false).build();
        SocketConfig socketConfig = SocketConfig.custom().setSoKeepAlive(true).setTcpNoDelay(true).build();

        PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
        poolingHttpClientConnectionManager.setMaxTotal(800);
        poolingHttpClientConnectionManager.setDefaultMaxPerRoute(700);

        CloseableHttpClient httpClientBuilder = HttpClientBuilder.create()
                .setConnectionManager(poolingHttpClientConnectionManager).setDefaultRequestConfig(requestConfig)
                .setDefaultSocketConfig(socketConfig).build();

        requestFactory.setHttpClient(httpClientBuilder);
        return requestFactory;
    }

}

这是人们通过传递dataKey对象来调用我们的库的方式:

DataResponse response = DataClientFactory.getInstance().getData(dataKey);

现在我的问题是:

如何决定我应该在setMaxTotal对象中为setDefaultMaxPerRoutePoolingHttpClientConnectionManager选择什么?截至目前,我的setMaxTotal和700 setDefaultMaxPerRoute为800?这是一个合理的数字还是我应该用别的东西?

我的客户端库将在多线程项目中使用非常繁重的负载。

3 个答案:

答案 0 :(得分:6)

没有可以应用于所有方案的公式或配方。通常使用阻塞i / o,每个路由设置的最大值应与争用连接的工作线程数大致相同。

因此,拥有15个工作线程和700个连接限制对我来说没什么意义。

答案 1 :(得分:2)

显然,对于这种情况,没有明确而有价值的公式。池化和吞吐量与响应时间之间的关系不够简单。我想到的一个特殊情况是,在某个值之后,响应时间会随着池大小的增加而开始增加。

通常使用阻塞i / o,每个路由设置的最大值应与争用连接的工作线程数大致相同。

答案 2 :(得分:0)

让我们尝试提出一个计算池大小的公式。

R: average response time of a http call in millisecond
Q: required throughput in requests per second

为了实现 Q ,您需要大约 t = Q * R / 1000 个主题来处理您的请求。对于所有这些不争用http连接的线程,您应该在任何时间点在池中至少有 t 连接。

实施例: 我有一个Web服务器,它获取结果并将其作为响应返回。

Q = 700 rps
X = 50 ms
t = 35

因此,您需要每个http路由至少35个连接,并且您的总连接数为35 *否。路线(3)。

PS:这是一个非常简单的公式,但是池化和吞吐量与响应时间之间的关系并不简单。我想到的一个特殊情况是,在某个值之后,响应时间会随着池大小的增加而开始增加。