httpclient的两个重要的参数maxPerRoute及MaxTotal

httpclient的连接池3个参数

HTTP请求时connectionRequestTimeout 、connectionTimeout、socketTimeout三个超时时间的含义
1.connectionRequestTimout:指从连接池获取连接的timeout

2.connetionTimeout:指客户端和服务器建立连接的timeout,

就是http请求的三个阶段,一:建立连接;二:数据传送;三,断开连接。超时后会ConnectionTimeOutException

3.socketTimeout:指客户端和服务器建立连接后,客户端从服务器读取数据的timeout,超出后会抛出SocketTimeOutException

httpclient封装了java中进行http网络请求的底层实现,是一个被广泛使用的组件。

httpclient是支持池化机制的,这两个参数maxPerRoute及MaxTotal就是表示池化设置的。

服务之间发送http请求常用的有Apache的Fluent以及spring的restTemplate等。对httpclient进行封装的有:Apache的Fluent、es的restHighLevelClient、spring的restTemplate等。

以ES的restHighLevelClient为例说明

  1. /**
  2. * Creates a new {@link RestClient} based on the provided configuration.
  3. */
  4. public RestClient build() {
  5. if (failureListener == null) {
  6. failureListener = new RestClient.FailureListener();
  7. }
  8. CloseableHttpAsyncClient httpClient = AccessController.doPrivileged(new PrivilegedAction<CloseableHttpAsyncClient>() {
  9. @Override
  10. public CloseableHttpAsyncClient run() {
  11. return createHttpClient();
  12. }
  13. });
  14. RestClient restClient = new RestClient(httpClient, defaultHeaders, nodes,
  15. pathPrefix, failureListener, nodeSelector, strictDeprecationMode);
  16. httpClient.start();
  17. return restClient;
  18. }
  19. private CloseableHttpAsyncClient createHttpClient() {
  20. //default timeouts are all infinite
  21. RequestConfig.Builder requestConfigBuilder = RequestConfig.custom()
  22. .setConnectTimeout(DEFAULT_CONNECT_TIMEOUT_MILLIS)
  23. .setSocketTimeout(DEFAULT_SOCKET_TIMEOUT_MILLIS);
  24. if (requestConfigCallback != null) {
  25. requestConfigBuilder = requestConfigCallback.customizeRequestConfig(requestConfigBuilder);
  26. }
  27.  
  28. try {
  29. HttpAsyncClientBuilder httpClientBuilder = HttpAsyncClientBuilder.create().setDefaultRequestConfig(requestConfigBuilder.build())
  30. //default settings for connection pooling may be too constraining
  31. .setMaxConnPerRoute(DEFAULT_MAX_CONN_PER_ROUTE).setMaxConnTotal(DEFAULT_MAX_CONN_TOTAL)
  32. .setSSLContext(SSLContext.getDefault())
  33. .setTargetAuthenticationStrategy(new PersistentCredentialsAuthenticationStrategy());
  34. if (httpClientConfigCallback != null) {
  35. httpClientBuilder = httpClientConfigCallback.customizeHttpClient(httpClientBuilder);
  36. }
  37.  
  38. final HttpAsyncClientBuilder finalBuilder = httpClientBuilder;
  39. return AccessController.doPrivileged(new PrivilegedAction<CloseableHttpAsyncClient>() {
  40. @Override
  41. public CloseableHttpAsyncClient run() {
  42. return finalBuilder.build();
  43. }
  44. });
  45. } catch (NoSuchAlgorithmException e) {
  46. throw new IllegalStateException("could not create the default ssl context", e);
  47. }
  48. }

例子2:Apache的Fluent,其Executor类

  1. /**
  2. * An Executor for fluent requests
  3. * <p/>
  4. * A {@link PoolingHttpClientConnectionManager} with maximum 100 connections per route and
  5. * a total maximum of 200 connections is used internally.
  6. */
  7. //最大100 connections per route 以及 最大200个 connection
  8.  
  9. CONNMGR = new PoolingHttpClientConnectionManager(sfr);
  10.  
  11. CONNMGR.setDefaultMaxPerRoute(100);
  12.  
  13. CONNMGR.setMaxTotal(200);
  14.  
  15. CLIENT = HttpClientBuilder.create().setConnectionManager(CONNMGR).build();

maxPerRoute及MaxTotal参数含义

maxPerRoute及MaxTotal这两个参数的含义是什么呢?

下面用测试代码说明一下

测试端

  1. public class HttpFluentUtil {
  2. private Logger logger = LoggerFactory.getLogger(HttpFluentUtil.class);
  3. private final static int MaxPerRoute = 2;
  4. private final static int MaxTotal = 4;
  5. final static PoolingHttpClientConnectionManager CONNMGR;
  6. final static HttpClient CLIENT;
  7. final static Executor EXECUTOR;
  8. static {
  9. LayeredConnectionSocketFactory ssl = null;
  10. try {
  11. ssl = SSLConnectionSocketFactory.getSystemSocketFactory();
  12. } catch (final SSLInitializationException ex) {
  13. final SSLContext sslcontext;
  14. try {
  15. sslcontext = SSLContext.getInstance(SSLConnectionSocketFactory.TLS);
  16. sslcontext.init(null, null, null);
  17. ssl = new SSLConnectionSocketFactory(sslcontext);
  18. } catch (final SecurityException ignore) {
  19. } catch (final KeyManagementException ignore) {
  20. } catch (final NoSuchAlgorithmException ignore) {
  21. }
  22. }
  23. final Registry<ConnectionSocketFactory> sfr = RegistryBuilder.<ConnectionSocketFactory>create()
  24. .register("http", PlainConnectionSocketFactory.getSocketFactory())
  25. .register("https", ssl != null ? ssl : SSLConnectionSocketFactory.getSocketFactory()).build();
  26. CONNMGR = new PoolingHttpClientConnectionManager(sfr);
  27. CONNMGR.setDefaultMaxPerRoute(MaxPerRoute);
  28. CONNMGR.setMaxTotal(MaxTotal);
  29. CLIENT = HttpClientBuilder.create().setConnectionManager(CONNMGR).build();
  30. EXECUTOR = Executor.newInstance(CLIENT);
  31. }
  32. public static String Get(String uri, int connectTimeout, int socketTimeout) throws IOException {
  33. return EXECUTOR.execute(Request.Get(uri).connectTimeout(connectTimeout).socketTimeout(socketTimeout))
  34. .returnContent().asString();
  35. }
  36. public static String Post(String uri, StringEntity stringEntity, int connectTimeout, int socketTimeout)
  37. throws IOException {
  38. return EXECUTOR.execute(Request.Post(uri).socketTimeout(socketTimeout)
  39. .addHeader("Content-Type", "application/json").body(stringEntity)).returnContent().asString();
  40. }
  41. public static void main(String[] args) {
  42. HttpUtil httpUtil = new HttpUtil();
  43. String url = "http://localhost:9064/app/test"; // 服务端sleep 5秒再返回
  44. for (int i = 0; i < 5; i++) { // MaxPerRoute若设置为2,则5线程分3组返回(2、2、1),共15秒
  45. new Thread(new Runnable() {
  46. @Override
  47. public void run() {
  48. try {
  49. String result = HttpFluentUtil.Get(url, 2000, 2000);
  50. System.out.println(result);
  51. } catch (IOException e) {
  52. e.printStackTrace();
  53. }
  54. }
  55. }).start();
  56. }
  57. }
  58. }

服务器端

很简单的springmvc

  1. @GetMapping(value="test")
  2. public String test() throws InterruptedException {
  3. Thread.sleep(1000);
  4. return "1";
  5. }

测试1:测试端MaxPerRoute=5 MaxTotal=4

服务器端结果

可以看到先接收4个请求,处理完成后,再接收下一次剩余的1个请求。即其一次最多接收MaxTotal次请求

测试2:测试端MaxPerRoute=2 MaxTotal=5

服务器端结果

可以看到接收2个请求,2个请求,1个请求,即说明maxPerRoute意思是某一个服务每次能并行接收的请求数量。

什么场景下要设置?

知道了两个参数的含义,那么在什么情况下要对这两个参数进行设置呢?

比如说下面的场景

服务1要通过Fluent调用服务2的接口。服务1发送了400个请求,但由于Fluent默认只支持maxPerRoute=100,MaxTotal=200,比如接口执行时间为500ms,由于maxPerRoute=100,所以要分为100,100,100,100分四批来执行,全部执行完成需要2000ms。而如果maxPerRoute设置为400,全部执行完需要500ms。在这种情况下(提供并发能力时)就要对这两个参数进行设置了。

设置的方法

1、Apache Fluent可以使用上面测试的HttpFluentUtil工具类来执行请求

2、RestTemplate类似使用下面的方式

  1. @Bean
  2. public HttpClient httpClient() {
  3. Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
  4. .register("http", PlainConnectionSocketFactory.getSocketFactory())
  5. .register("https", SSLConnectionSocketFactory.getSocketFactory())
  6. .build();
  7. PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
  8. connectionManager.setMaxTotal(restTemplateProperties.getMaxTotal());
  9. connectionManager.setDefaultMaxPerRoute(restTemplateProperties.getDefaultMaxPerRoute());
  10. connectionManager.setValidateAfterInactivity(restTemplateProperties.getValidateAfterInactivity());
  11. RequestConfig requestConfig = RequestConfig.custom()
  12. .setSocketTimeout(restTemplateProperties.getSocketTimeout())
  13. .setConnectTimeout(restTemplateProperties.getConnectTimeout())
  14. .setConnectionRequestTimeout(restTemplateProperties.getConnectionRequestTimeout())
  15. .build();
  16. return HttpClientBuilder.create()
  17. .setDefaultRequestConfig(requestConfig)
  18. .setConnectionManager(connectionManager)
  19. .build();
  20.  
  21. }
  22. @Bean
  23. public ClientHttpRequestFactory httpRequestFactory() {
  24. return new HttpComponentsClientHttpRequestFactory(httpClient());
  25. }
  26. @Bean
  27. public RestTemplate restTemplate() {
  28. return new RestTemplate(httpRequestFactory());
  29. }

其中RestTemplateProperties通过配置文件来配置

  1. max-total
  2. default-max-per-route
  3. connect-timeout 获取连接超时
  4. connection-request-timeout 请求超时
  5. socket-timeout 读超时

3、ES的restHighLevelClient设置

  1. @Bean
  2. public RestHighLevelClient restHighLevelClient(){
  3. //解析hostlist配置信息
  4. String[] split = hostlist.split(",");
  5. //创建HttpHost数组,其中存放es主机和端口的配置信息
  6. HttpHost[] httpHostArray = new HttpHost[split.length];
  7. for(int i=0;i<split.length;i++){
  8. String item = split[i];
  9. httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
  10. }
  11. //创建RestHighLevelClient客户端
  12. //return new RestHighLevelClient(RestClient.builder(httpHostArray));//.setMaxRetryTimeoutMillis(5 * 60 * 1000)); //超时时间设为5分钟);
  13. RestClientBuilder builder = RestClient.builder(httpHostArray);
  14.  
  15. builder.setRequestConfigCallback(requestConfigBuilder -> {
  16. requestConfigBuilder.setConnectTimeout(connectTimeoutMillis);
  17. requestConfigBuilder.setSocketTimeout(socketTimeoutMillis);
  18. requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeoutMillis);
  19. return requestConfigBuilder;
  20. });
  21.  
  22. builder.setHttpClientConfigCallback(httpClientBuilder -> {
  23. httpClientBuilder.setMaxConnTotal(maxConnectTotal);
  24. httpClientBuilder.setMaxConnPerRoute(maxConnectPerRoute);
  25. return httpClientBuilder;
  26. });
  27.  
  28. return new RestHighLevelClient(builder);
  29.  
  30. }

里面的5个变量,通过spring的@Value注入,这里省略。

总结:

  1. max-total:连接池里的最大连接数
  2. default-max-per-route某一个/每服务每次能并行接收的请求数量
  3. connect-timeout 从连接池里获取连接超时时间
  4. connection-request-timeout 请求超时时间
  5. socket-timeout 读超时时间

参考:https://blog.csdn.net/u013905744/java/article/details/94714696

Tomcat安全的更多相关文章

  1. Tomcat一个BUG造成CLOSE_WAIT

    之前应该提过,我们线上架构整体重新架设了,应用层面使用的是Spring Boot,前段日子因为一些第三方的原因,略有些匆忙的提前开始线上的内测了.然后运维发现了个问题,服务器的HTTPS端口有大量的C ...

  2. docker——容器安装tomcat

    写在前面: 继续docker的学习,学习了docker的基本常用命令之后,我在docker上安装jdk,tomcat两个基本的java web工具,这里对操作流程记录一下. 软件准备: 1.jdk-7 ...

  3. Tomcat shutdown执行后无法退出进程问题排查及解决

    问题定位及排查 上周无意中调试程序在Linux上ps -ef|grep tomcat发现有许多tomcat的进程,当时因为没有影响系统运行就没当回事.而且我内心总觉得这可能是tomcat像nginx一 ...

  4. 记一次tomcat线程创建异常调优:unable to create new native thread

    测试在进行一次性能测试的时候发现并发300个请求时出现了下面的异常: HTTP Status 500 - Handler processing failed; nested exception is ...

  5. Linux CentOS 配置Tomcat环境

    一.下载Tomcat 下载Tomcat方式也有两种,可以参考我的前一篇博文Linux CentOS配置JDK环境,这边就不再赘述. 二.在Linux处理Tomcat包 1.创建tomcat文件夹 mk ...

  6. 在Linux虚拟机下配置tomcat

    1.到Apache官网下载tomcat http://tomcat.apache.org/download-80.cgi 博主我下载的是tomcat8 博主的jdk是1.8 如果你们的jdk是1.7或 ...

  7. tomcat开发远程调试端口以及利用eclipse进行远程调试

    一.tomcat开发远程调试端口 方法1 WIN系统 在catalina.bat里:  SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Djava.compi ...

  8. Eclipse中启动tomcat报错java.lang.OutOfMemoryError: PermGen space的解决方法

    有的项目引用了太多的jar包,或者反射生成了太多的类,异或有太多的常量池,就有可能会报java.lang.OutOfMemoryError: PermGen space的错误, 我们知道可以通过jvm ...

  9. mac下安装及配置tomcat

    mac下的软件不像windows下的程序那样写注册表,对于tomcat的安装来说,在mac下是名符其实的绿色软件,具体操作如下: 1.到 apache官方主页 下载完整 tar.gz文件包.(没有专门 ...

  10. 设置tomcat远程debug

    查看端口占用情况命令: netstat -tunlp |grep 8000 tomcat 启动远程debug: startup.sh 中的最后一行 exec "$PRGDIR"/& ...

随机推荐

  1. python学习笔记20(字符串格式化)

    Python中内置有对字符串进行格式化的操作% 模板 格式化字符串时,Python使用一个字符串作为模板.模板中有格式符,这些格式符为真实值预留位置,并说明真实数值应该呈现的格式.Python用一个t ...

  2. 1200: [HNOI2005]木梳 - BZOJ

    Description   Input 第一行为整数L,其中4<=L<=100000,且有50%的数据满足L<=104,表示木板下侧直线段的长.第二行为L个正整数A1,A2,…,AL ...

  3. 转Spring+Hibernate+EHcache配置(二)

    Spring AOP+EHCache简单缓存系统解决方案 需要使用Spring来实现一个Cache简单的解决方案,具体需求如下:使用任意一个现有开源Cache Framework,要求可以Cache系 ...

  4. C++中cin、cin.get()、cin.getline()、getline()、gets()等函数的用法

    学C++的时候,这几个输入函数弄的有点迷糊:这里做个小结,为了自己复习,也希望对后来者能有所帮助,如果有差错的地方还请各位多多指教(本文所有程序均通过VC 6.0运行) 1.cin 2.cin.get ...

  5. uploadify 下载组件使用技巧和在线预览 word,excel,ppt,pdf的方案

    http://www.cnblogs.com/wolf-sun/p/3565184.html uploadify 上传工具的使用技巧 http://www.cnblogs.com/wolf-sun/p ...

  6. 多线程 (四)GCD

    学习GCD要掌握几个概念 任务:需要执行的代码块可以看作一个任务 队列:把任务放到队列里,遵循先进先出的原则 队列又分为串行队列和并行队列 串行队列:顺序执行 并发队列:同时执行多个任务 同步:在当前 ...

  7. CURL与PHP-CLI的应用【CLI篇】

    CLI的普通应用 什么是PHP-CLI php-cli是php Command Line Interface的简称,即PHP命令行接口,在windows和linux下都是支持PHP-CLI模式的; 为 ...

  8. 跨平台的目录遍历实现方法(windows和linux已经测试)

    dirent.h是gcc下的一个头文件,在windows中是没有的.这个文件中封装了几个对目录进行操作函数: static DIR *opendir (const char *dirname);sta ...

  9. QDialog之屏蔽Esc键(过滤,或者丢弃)

    http://blog.csdn.net/u011012932/article/details/50357323

  10. P154、面试题28:字符串的排列

    题目:输入一个字符串,打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a.b.c所能排列出来的所有字符串abc.acb.bac.bca.cab.cba. 测试用例: 1)功能测试( ...