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

How to decide optimal settings for setMaxTotal and setDefaultMaxPerRoute?

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

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

我正在使用 RestTemplateHttpComponentsClientHttpRequestFactory,如下所示:

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

现在我的问题是:

如何决定PoolingHttpClientConnectionManager对象中的setMaxTotalsetDefaultMaxPerRoute应该选择什么?截至目前,我要为 setMaxTotal 和 700 setDefaultMaxPerRoute 准备 800 个?这是一个合理的数字还是我应该选择其他数字?

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

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

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

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

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

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

示例: 我有一个网络服务器,它获取结果并 return 作为响应。

Q = 700 rps
X = 50 ms
t = 35

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

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

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

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