本文是HttpClient的学习博客,RestTemplate是基于HttpClient的封装,feign可基于HttpClient进行网络通信。

  那么作为较底层的客户端网络编程框架,该怎么配置使其能高可用,高并发,可支持Https协议呢?通读本文也许你会有答案或者启发。

  本文是Maven项目,基于Spring,在本Demo中使用了更方便的SpringBoot。

  以后随着理解HttpClient更深入的时候会不定期更新本博客,也欢迎感兴趣的博友交流和讨论。

一、本文目录

  1. 代码实现

  2. 测试验证

  3. 后记

二、代码实现

1. 项目依赖

 1 <dependency>
2 <groupId>org.springframework.boot</groupId>
3 <artifactId>spring-boot-starter</artifactId>
4 </dependency>
5
6 <!--httpclient-->
7 <dependency>
8 <groupId>org.apache.httpcomponents</groupId>
9 <artifactId>httpclient</artifactId>
10 <version>4.5.12</version>
11 </dependency>
12
13 <!--alibaba JSON-->
14 <dependency>
15 <groupId>com.alibaba</groupId>
16 <artifactId>fastjson</artifactId>
17 <version>1.2.70</version>
18 </dependency>
19
20 <dependency>
21 <groupId>org.springframework.boot</groupId>
22 <artifactId>spring-boot-starter-test</artifactId>
23 <scope>test</scope>
24 </dependency>

pom.xml

2. 项目结构

  

3. 项目配置

 1 #HttpClient配置
2 httpClient:
3 #重试次数
4 retryCount: 3
5 #重启开关
6 requestSentRetryEnabled: true
7 #HttpClient连接池配置
8 pool:
9 #总连接数
10 maxTotal: 200
11 #每个路由默认连接数,某一个/每服务每次能并行接收的请求数量
12 defaultMaxPerRoute: 50
13 #Validate connections after 15 sec of inactivity 15000
14 validateAfterInactivity: 1000
15 #idle超时时间
16 idleTimeOut: 3
17 socketCfg:
18 #是否立即发送数据,设置为true会关闭Socket缓冲,默认为false
19 tcpNoDelay: true
20 #是否可以在一个进程关闭Socket后,即使它还没有释放端口,其它进程还可以立即重用端口
21 soReuseAddress: true
22 #接受数据的等待超时时间,单位ms
23 soTimeOut: 500
24 #关闭Socket时,要么发送完所有数据,要么等待60s后,就关闭连接,此时socket.close()是阻塞的
25 soLinger: 60
26 #开启监视TCP连接是否有效
27 soKeepAlive: true

application.yml

4. HttpClient客户端配置类

  通过配置连接池管理对象PoolingHttpClientConnectionManager,设置两个重要参数maxTotal和defaultMaxPerRoute,及其其它参数。本文参数配置参考官方文档httpcomponents-client-4.5.x,文档上面的参数更多更齐全,包括HttpConnectionFactory、DnsResolver、ConnectionConfig、RequestConfig、RequestConfig、HttpClientContext、设置代理。这些参数本文没有配置,使用HttpClient的默认配置,感兴趣想继续深入研究的可以去学习了解。BackoffManager可以在连接池处于闲暇时进行收缩,不过网络上资料较少,目前还没研究出怎么使用和配置。

  1 package com.example.httpclientdemo.common.config.http.client;
2
3 import org.apache.http.config.Registry;
4 import org.apache.http.config.RegistryBuilder;
5 import org.apache.http.config.SocketConfig;
6 import org.apache.http.conn.socket.ConnectionSocketFactory;
7 import org.apache.http.conn.socket.PlainConnectionSocketFactory;
8 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
9 import org.apache.http.impl.client.*;
10 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
11 import org.apache.http.ssl.SSLContexts;
12 import org.springframework.beans.factory.annotation.Value;
13 import org.springframework.context.annotation.Bean;
14 import org.springframework.context.annotation.Configuration;
15
16 import java.util.concurrent.TimeUnit;
17
18 /**
19 * HttpClient客户端配置类
20 *
21 * @author 复姓江山
22 * @date 2021/02/08
23 */
24 @Configuration
25 public class HttpClientConfig {
26
27 /**
28 * closeableHttpClient连接对象,支持HTTPS使用SSL套接层
29 *
30 * @param httpClientPoolManager HttpClient连接池管理对象
31 * @param retryCount 重试次数
32 * @param requestSentRetryEnabled 重启开关
33 * @return closeableHttpClient连接对象
34 */
35 @Bean
36 public CloseableHttpClient closeableHttpClient(final PoolingHttpClientConnectionManager httpClientPoolManager,
37 @Value("${httpClient.retryCount}") final int retryCount,
38 @Value("${httpClient.requestSentRetryEnabled}") final
39 boolean requestSentRetryEnabled) {
40
41 return HttpClients.custom()
42 .setDefaultCookieStore(new BasicCookieStore())
43 .setDefaultCredentialsProvider(new BasicCredentialsProvider())
44 .setConnectionManager(httpClientPoolManager)
45 .setRetryHandler(new DefaultHttpRequestRetryHandler(retryCount, requestSentRetryEnabled))
46 .build();
47 }
48
49 /**
50 * 默认socket configuration
51 *
52 * @param tcpNoDelay 是否立即发送数据,设置为true会关闭Socket缓冲,默认为false
53 * @param soReuseAddress 是否可以在一个进程关闭Socket后,即使它还没有释放端口,其它进程还可以立即重用端口
54 * @param soTimeOut 接受数据的等待超时时间,单位ms
55 * @param soLinger 关闭Socket时,要么发送完所有数据,要么等待60s后,就关闭连接,此时socket.close()是阻塞的
56 * @param soKeepAlive 开启监视TCP连接是否有效
57 * @return 默认socket configuration
58 */
59 @Bean
60 public SocketConfig defaultSocketConfig(@Value("${httpClient.pool.socketCfg.tcpNoDelay}") final boolean tcpNoDelay,
61 @Value("${httpClient.pool.socketCfg.soReuseAddress}") final boolean soReuseAddress,
62 @Value("${httpClient.pool.socketCfg.soTimeOut}") final int soTimeOut,
63 @Value("${httpClient.pool.socketCfg.soLinger}") final int soLinger,
64 @Value("${httpClient.pool.socketCfg.soKeepAlive}") final boolean soKeepAlive) {
65 return SocketConfig.custom()
66 .setTcpNoDelay(tcpNoDelay)
67 .setSoReuseAddress(soReuseAddress)
68 .setSoTimeout(soTimeOut)
69 .setSoLinger(soLinger)
70 .setSoKeepAlive(soKeepAlive).build();
71 }
72
73 /**
74 * HttpClient连接池管理对象
75 *
76 * @param maxTotal 总连接数
77 * @param defaultMaxPerRoute 每个路由默认连接数,某一个/每服务每次能并行接收的请求数量
78 * @param validateAfterInactivity 一次连接保留时长,单位s
79 * @param idleTimeOut idle超时时间
80 * @param defaultSocketConfig 默认socket configuration
81 * @return HttpClient连接池管理对象
82 */
83 @Bean
84 public PoolingHttpClientConnectionManager httpClientPoolManager(
85 @Value("${httpClient.pool.maxTotal}") final int maxTotal,
86 @Value("${httpClient.pool.defaultMaxPerRoute}") final int defaultMaxPerRoute,
87 @Value("${httpClient.pool.validateAfterInactivity}") final int validateAfterInactivity,
88 @Value("${httpClient.pool.validateAfterInactivity}") final long idleTimeOut,
89 final SocketConfig defaultSocketConfig) {
90 Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
91 .register("http", PlainConnectionSocketFactory.INSTANCE)
92 .register("https", new SSLConnectionSocketFactory(SSLContexts.createSystemDefault()))
93 .build();
94 PoolingHttpClientConnectionManager poolManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
95 poolManager.setMaxTotal(maxTotal);
96 poolManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
97 poolManager.setValidateAfterInactivity(validateAfterInactivity);
98 poolManager.closeIdleConnections(idleTimeOut, TimeUnit.SECONDS);
99 poolManager.setDefaultSocketConfig(defaultSocketConfig);
100 return poolManager;
101 }
102
103 }

HttpClientConfig.java

5. HttpClient工具类

  1 package com.example.httpclientdemo.common.utils.http.client;
2
3 import org.apache.http.HttpEntity;
4 import org.apache.http.client.methods.*;
5 import org.apache.http.impl.client.CloseableHttpClient;
6 import org.apache.http.impl.execchain.RequestAbortedException;
7
8 import java.io.*;
9 import java.util.stream.Collectors;
10
11 /**
12 * HttpClient工具类
13 *
14 * @author 复姓江山
15 * @date 2021/02/08
16 */
17 public final class HttpClientUtils {
18
19 /**
20 * header的Content-Type键
21 */
22 public final static String HEADER_CONTENT_TYPE = "Content-Type";
23
24 /**
25 * R3C默认Content_Type
26 */
27 public final static String R3C_DEFAULT_CONTENT_TYPE = "application/vnd.api+json";
28
29 /**
30 * Authorization
31 */
32 public final static String HEADER_AUTHORIZATION = "Authorization";
33
34 private HttpClientUtils() {
35
36 }
37
38 /**
39 * httpClient的响应实体
40 *
41 * @param httpClient httpClient对象
42 * @param request 请求对象
43 * @return 响应实体
44 * @throws IOException IO异常
45 */
46 private static CloseableHttpResponse httpResponse(CloseableHttpClient httpClient,
47 HttpUriRequest request) throws IOException {
48 return httpClient.execute(request);
49 }
50
51 /**
52 * get请求
53 *
54 * @param httpClient httpClient对象
55 * @param request 请求对象
56 * @return 响应实体
57 * @throws IOException IO异常
58 */
59 public static CloseableHttpResponse get(CloseableHttpClient httpClient, HttpUriRequest request) throws IOException {
60 assert HttpGet.METHOD_NAME.equals(request.getMethod());
61 return HttpClientUtils.httpResponse(httpClient, request);
62 }
63
64 /**
65 * post请求
66 *
67 * @param httpClient httpClient对象
68 * @param request 请求对象
69 * @return 响应实体
70 * @throws IOException IO异常
71 */
72 public static CloseableHttpResponse post(CloseableHttpClient httpClient, HttpUriRequest request) throws IOException {
73 assert HttpPost.METHOD_NAME.equals(request.getMethod());
74 return HttpClientUtils.httpResponse(httpClient, request);
75 }
76
77 /**
78 * post或patch请求
79 *
80 * @param httpClient httpClient对象
81 * @param request 请求对象
82 * @return 响应实体
83 * @throws IOException IO异常
84 */
85 public static CloseableHttpResponse postOrPatch(CloseableHttpClient httpClient, HttpUriRequest request) throws IOException {
86 if (request instanceof HttpPost) {
87 assert HttpPost.METHOD_NAME.equals(request.getMethod());
88 } else if (request instanceof HttpPatch) {
89 assert HttpPatch.METHOD_NAME.equals(request.getMethod());
90 } else {
91 throw new RequestAbortedException("Not post or patch.");
92 }
93 return HttpClientUtils.httpResponse(httpClient, request);
94 }
95
96 /**
97 * patch请求
98 *
99 * @param httpClient httpClient对象
100 * @param request 请求对象
101 * @return 响应实体
102 * @throws IOException IO异常
103 */
104 public static CloseableHttpResponse patch(CloseableHttpClient httpClient, HttpUriRequest request) throws IOException {
105 assert HttpPatch.METHOD_NAME.equals(request.getMethod());
106 return HttpClientUtils.httpResponse(httpClient, request);
107 }
108
109 /**
110 * httpClient的HttpEntity
111 *
112 * @param response 响应实体
113 * @return HttpEntity
114 */
115 public static HttpEntity httpEntity(final CloseableHttpResponse response) {
116 return response.getEntity();
117 }
118
119
120 /**
121 * 返回状态行代码
122 *
123 * @param response 响应实体
124 * @return 状态行代码
125 */
126 public static int getStatusCode(final CloseableHttpResponse response) {
127 return response.getStatusLine().getStatusCode();
128 }
129
130 /**
131 * 获取ContentType
132 *
133 * @param httpEntity HttpEntity
134 * @return ContentType
135 */
136 public static String getContentType(final HttpEntity httpEntity) {
137 return httpEntity.getContentType().getValue();
138 }
139
140 /**
141 * 获取ContentEncoding
142 *
143 * @param httpEntity HttpEntity
144 * @return ContentEncoding
145 */
146 public static String getContentEncoding(final HttpEntity httpEntity) {
147 return httpEntity.getContentEncoding().getValue();
148 }
149
150 /**
151 * 获取响应体对象InputStream
152 *
153 * @param httpEntity HttpEntity
154 * @return 获取响应体对象InputStream
155 * @throws IOException IO异常
156 */
157 public static InputStream getContent(final HttpEntity httpEntity) throws IOException {
158 return httpEntity.getContent();
159 }
160
161 /**
162 * 获取响应体对象的字符串
163 *
164 * @param inputStream InputStream
165 * @return 获取响应体对象InputStream
166 * @throws IOException IO异常
167 */
168 public static String getContentString(final InputStream inputStream) throws IOException {
169 return new BufferedReader(new InputStreamReader(inputStream))
170 .lines().parallel().collect(Collectors.joining(System.lineSeparator()));
171 }
172
173 /**
174 * 获取响应体对象的字符串
175 *
176 * @param httpEntity HttpEntity
177 * @return 获取响应体对象InputStream
178 * @throws IOException IO异常
179 */
180 public static String getContentString(final HttpEntity httpEntity) throws IOException {
181 return new BufferedReader(new InputStreamReader(HttpClientUtils.getContent(httpEntity)))
182 .lines().parallel().collect(Collectors.joining(System.lineSeparator()));
183 }
184
185 /**
186 * 字符串转InputStream
187 *
188 * @param str 字符串
189 * @return inputStream
190 */
191 public static InputStream stringTransferToInputStream(String str) {
192 return new ByteArrayInputStream(str.getBytes());
193 }
194
195 /**
196 * 设置默认的Content-Type
197 *
198 * @param request http请求对象
199 */
200 public static void setDefaultContentType(HttpUriRequest request) {
201 request.setHeader(HttpClientUtils.HEADER_CONTENT_TYPE, HttpClientUtils.R3C_DEFAULT_CONTENT_TYPE);
202 }
203
204 /**
205 * 设置Authorization
206 *
207 * @param request http请求对象
208 * @param token token
209 */
210 public static void setAuthorization(HttpUriRequest request, String token) {
211 request.setHeader(HttpClientUtils.HEADER_AUTHORIZATION, token);
212 }
213
214 /**
215 * 设置默认请求头
216 *
217 * @param request http请求对象
218 * @param token token
219 */
220 public static void setDefaultHeader(HttpUriRequest request, String token) {
221 HttpClientUtils.setDefaultContentType(request);
222 HttpClientUtils.setAuthorization(request, token);
223 }
224
225 /**
226 * 关闭连接
227 *
228 * @param response response响应对象
229 * @param inputStream inputStream
230 */
231 public static void close(CloseableHttpResponse response, InputStream inputStream) throws IOException {
232 if (inputStream != null) {
233 inputStream.close();
234 }
235 if (response != null) {
236 response.close();
237 }
238 }
239
240
241 }

HttpClientUtils.java

6. HttpClient业务接口及其实现

 1 package com.example.httpclientdemo.biz.service;
2
3 /**
4 * HttpClient业务接口类
5 *
6 * @author 复姓江山
7 * @date 2021/02/08
8 */
9 public interface HttpClientService {
10 /**
11 * get请求
12 *
13 * @param url 请求地址
14 */
15 void requestGet(String url);
16
17 /**
18 * post请求
19 *
20 * @param url 请求地址
21 * @param obj 请求对象
22 */
23 void requestPost(String url, Object obj);
24 }

HttpClientService.java

 1 package com.example.httpclientdemo.biz.service.impl;
2
3 import com.example.httpclientdemo.biz.provider.HttpClientProvider;
4 import com.example.httpclientdemo.biz.service.HttpClientService;
5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.stereotype.Service;
7
8 /**
9 * HttpClient业务接口实现类
10 *
11 * @author 复姓江山
12 * @date 2021/02/08
13 */
14 @Service
15 public class HttpClientServiceImpl implements HttpClientService {
16
17 @Autowired
18 private HttpClientProvider httpClientProvider;
19
20
21 @Override
22 public void requestGet(String url) {
23 httpClientProvider.requestGet(url);
24 }
25
26 @Override
27 public void requestPost(String url, Object obj) {
28 httpClientProvider.requestPost(url, obj);
29 }
30 }

HttpClientServiceImpl.java

7. HttpClient业务支撑接口及其实现

  为什么会加个业务支撑接口呢?常见的分层结构或分层架构(控制层、业务层和数据访问层——分层结构,或表示层(UI)、业务逻辑层(BLL)和数据访问层——分层架构),在此基础上增加provder是因为多层封装与隔离,HttpClient是作为客户端请求其它系统服务,请求参数与相应参数及异常处理应与本项目进行一定隔离,如果把HttpClient客户端深度耦合到业务层中,到对方服务器变动时,就会影响本系统的核心业务逻辑。而增加了封装与隔离后,影响的只是provider层,系统本身的核心业务逻辑不会受到深层次的影响。在这我就稍微发散一下思维,比如定义一个MQ的接口,在使用的是Kafka,RabitMQ,ActiveMQ或者RocketMQ,不管怎么变更MQ,系统业务代码依赖的是MQ的接口,丝毫不会受到影响。所以编程原则里有一条:面向接口编程,面向抽象编程。

 1 package com.example.httpclientdemo.biz.provider;
2
3 /**
4 * HttpClient业务支撑接口类
5 *
6 * @author 复姓江山
7 * @date 2021/02/08
8 */
9 public interface HttpClientProvider {
10
11 /**
12 * get请求
13 *
14 * @param url 请求地址
15 */
16 void requestGet(String url);
17
18 /**
19 * post请求
20 *
21 * @param url 请求地址
22 * @param obj 请求参数
23 */
24 void requestPost(String url, Object obj);
25 }

HttpClientProvider.java

 1 package com.example.httpclientdemo.biz.provider.impl;
2
3 import com.alibaba.fastjson.JSON;
4 import com.example.httpclientdemo.biz.provider.HttpClientProvider;
5 import com.example.httpclientdemo.common.utils.http.client.HttpClientUtils;
6 import org.apache.http.HttpEntity;
7 import org.apache.http.client.methods.CloseableHttpResponse;
8 import org.apache.http.client.methods.HttpGet;
9 import org.apache.http.client.methods.HttpPost;
10 import org.apache.http.entity.StringEntity;
11 import org.apache.http.impl.client.CloseableHttpClient;
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
14 import org.springframework.stereotype.Service;
15
16 import javax.annotation.Resource;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.nio.charset.StandardCharsets;
20
21 /**
22 * HttpClient业务支撑接口实现类
23 *
24 * @author 复姓江山
25 * @date 2021/02/08
26 */
27 @Service
28 public class HttpClientProviderImpl implements HttpClientProvider {
29 private final Logger logger = LoggerFactory.getLogger(this.getClass());
30
31 @Resource(name = "closeableHttpClient")
32 private CloseableHttpClient httpClient;
33
34
35 @Override
36 public void requestGet(String url) {
37 HttpGet httpGet = new HttpGet(url);
38 CloseableHttpResponse response = null;
39 InputStream inputStream = null;
40
41 try {
42 response = HttpClientUtils.get(httpClient, httpGet);
43 HttpEntity httpEntity = response.getEntity();
44 inputStream = HttpClientUtils.getContent(httpEntity);
45 String respString = HttpClientUtils.getContentString(inputStream);
46 logger.debug("respString: {}", respString);
47 } catch (Exception e) {
48 e.fillInStackTrace();
49 } finally {
50 try {
51 HttpClientUtils.close(response, inputStream);
52 } catch (IOException ioException) {
53 ioException.printStackTrace();
54 }
55 }
56 }
57
58 @Override
59 public void requestPost(String url, Object obj) {
60 HttpPost httpPost = new HttpPost(url);
61 String jsonString = JSON.toJSONString(obj);
62 httpPost.setEntity(new StringEntity(jsonString, StandardCharsets.UTF_8));
63 CloseableHttpResponse response = null;
64 InputStream inputStream = null;
65 try {
66 response = HttpClientUtils.post(httpClient, httpPost);
67 HttpEntity httpEntity = response.getEntity();
68 inputStream = HttpClientUtils.getContent(httpEntity);
69 String respString = HttpClientUtils.getContentString(inputStream);
70 logger.debug("respString: {}", respString);
71 } catch (Exception e) {
72 e.fillInStackTrace();
73 } finally {
74 try {
75 HttpClientUtils.close(response, inputStream);
76 } catch (IOException ioException) {
77 ioException.printStackTrace();
78 }
79 }
80 }
81 }

HttpClientProviderImpl.java

  8. HttpClient业务接口测试

  通过运行单元测试类来测试接口,下文有详细的测试数据。

 1 package com.example.httpclientdemo.biz.service;
2
3 import org.junit.jupiter.api.Test;
4 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory;
6 import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.boot.test.context.SpringBootTest;
8
9 import java.util.concurrent.ExecutorService;
10 import java.util.concurrent.Executors;
11 import java.util.concurrent.atomic.AtomicInteger;
12
13 import static org.junit.jupiter.api.Assertions.*;
14
15 @SpringBootTest
16 class HttpClientServiceTest {
17 private final static Logger logger = LoggerFactory.getLogger(HttpClientServiceTest.class);
18
19 @Autowired
20 private HttpClientService httpClientService;
21
22 private static final String URL_GET_PATH = "https://www.baidu.com";
23
24 private final AtomicInteger count = new AtomicInteger();
25
26 /**
27 * workStealingPool
28 */
29 public final static ExecutorService workStealingPool = Executors.newWorkStealingPool(1<<6);
30
31 @Test
32 void requestGet() throws InterruptedException {
33 final long startMils = System.currentTimeMillis();
34 final long statNanos = System.nanoTime();
35 for (int i = 0; i < 1000; i++) {
36 workStealingPool.execute(() -> {
37 httpClientService.requestGet(URL_GET_PATH);
38 logger.warn("requestGet, times: {}, betMils: {},betNanos: {}", count.getAndIncrement(),
39 (System.currentTimeMillis() - startMils), (System.nanoTime() - statNanos));
40 });
41
42 }
43 Thread.sleep(20000);
44 }
45
46 @Test
47 void requestPost() {
48 }
49 }

HttpClientServiceTest.java

三、测试验证

  本文测试方式可能不是那么专业与严谨,可是并不妨碍我们通过测试数据看出些原理,总结出些规律,也许有些片面,但可看出些趋势。

1. 运行日志

 1 main 2021-02-09 14:09:34,963 DEBUG (PoolingHttpClientConnectionManager.java:267)- Connection request: [route: {s}->https://www.baidu.com:443][total available: 0; route allocated: 0 of 50; total allocated: 0 of 200]
2 main 2021-02-09 14:09:34,978 DEBUG (PoolingHttpClientConnectionManager.java:312)- Connection leased: [id: 0][route: {s}->https://www.baidu.com:443][total available: 0; route allocated: 1 of 50; total allocated: 1 of 200]
3 main 2021-02-09 14:09:34,980 DEBUG (MainClientExec.java:234)- Opening connection {s}->https://www.baidu.com:443
4 main 2021-02-09 14:09:34,994 DEBUG (DefaultHttpClientConnectionOperator.java:139)- Connecting to www.baidu.com/14.215.177.38:443
5 main 2021-02-09 14:09:34,994 DEBUG (SSLConnectionSocketFactory.java:366)- Connecting socket to www.baidu.com/14.215.177.38:443 with timeout 0
6 main 2021-02-09 14:09:35,101 DEBUG (SSLConnectionSocketFactory.java:430)- Enabled protocols: [TLSv1, TLSv1.1, TLSv1.2]
7 main 2021-02-09 14:09:35,101 DEBUG (SSLConnectionSocketFactory.java:431)- Enabled cipher suites:[TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
8 main 2021-02-09 14:09:35,102 DEBUG (SSLConnectionSocketFactory.java:435)- Starting handshake
9 main 2021-02-09 14:09:35,250 DEBUG (SSLConnectionSocketFactory.java:465)- Secure session established
10 main 2021-02-09 14:09:35,250 DEBUG (SSLConnectionSocketFactory.java:466)- negotiated protocol: TLSv1.2
11 main 2021-02-09 14:09:35,250 DEBUG (SSLConnectionSocketFactory.java:467)- negotiated cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
12 main 2021-02-09 14:09:35,250 DEBUG (SSLConnectionSocketFactory.java:475)- peer principal: CN=baidu.com, O="Beijing Baidu Netcom Science Technology Co., Ltd", OU=service operation department, L=beijing, ST=beijing, C=CN
13 main 2021-02-09 14:09:35,251 DEBUG (SSLConnectionSocketFactory.java:484)- peer alternative names: [baidu.com, baifubao.com, www.baidu.cn, www.baidu.com.cn, mct.y.nuomi.com, apollo.auto, dwz.cn, *.baidu.com, *.baifubao.com, *.baidustatic.com, *.bdstatic.com, *.bdimg.com, *.hao123.com, *.nuomi.com, *.chuanke.com, *.trustgo.com, *.bce.baidu.com, *.eyun.baidu.com, *.map.baidu.com, *.mbd.baidu.com, *.fanyi.baidu.com, *.baidubce.com, *.mipcdn.com, *.news.baidu.com, *.baidupcs.com, *.aipage.com, *.aipage.cn, *.bcehost.com, *.safe.baidu.com, *.im.baidu.com, *.baiducontent.com, *.dlnel.com, *.dlnel.org, *.dueros.baidu.com, *.su.baidu.com, *.91.com, *.hao123.baidu.com, *.apollo.auto, *.xueshu.baidu.com, *.bj.baidubce.com, *.gz.baidubce.com, *.smartapps.cn, *.bdtjrcv.com, *.hao222.com, *.haokan.com, *.pae.baidu.com, *.vd.bdstatic.com, click.hm.baidu.com, log.hm.baidu.com, cm.pos.baidu.com, wn.pos.baidu.com, update.pan.baidu.com]
14 main 2021-02-09 14:09:35,251 DEBUG (SSLConnectionSocketFactory.java:488)- issuer principal: CN=GlobalSign Organization Validation CA - SHA256 - G2, O=GlobalSign nv-sa, C=BE
15 main 2021-02-09 14:09:35,254 DEBUG (DefaultHttpClientConnectionOperator.java:146)- Connection established 192.168.100.24:63820<->14.215.177.38:443
16 main 2021-02-09 14:09:35,255 DEBUG (MainClientExec.java:255)- Executing request GET / HTTP/1.1
17 main 2021-02-09 14:09:35,255 DEBUG (MainClientExec.java:260)- Target auth state: UNCHALLENGED
18 main 2021-02-09 14:09:35,255 DEBUG (MainClientExec.java:266)- Proxy auth state: UNCHALLENGED
19 main 2021-02-09 14:09:35,257 DEBUG (LoggingManagedHttpClientConnection.java:133)- http-outgoing-0 >> GET / HTTP/1.1
20 main 2021-02-09 14:09:35,257 DEBUG (LoggingManagedHttpClientConnection.java:136)- http-outgoing-0 >> Host: www.baidu.com
21 main 2021-02-09 14:09:35,257 DEBUG (LoggingManagedHttpClientConnection.java:136)- http-outgoing-0 >> Connection: Keep-Alive
22 main 2021-02-09 14:09:35,257 DEBUG (LoggingManagedHttpClientConnection.java:136)- http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.12 (Java/1.8.0_161)
23 main 2021-02-09 14:09:35,257 DEBUG (LoggingManagedHttpClientConnection.java:136)- http-outgoing-0 >> Accept-Encoding: gzip,deflate
24 main 2021-02-09 14:09:35,258 DEBUG (Wire.java:73)- http-outgoing-0 >> "GET / HTTP/1.1[\r][\n]"
25 main 2021-02-09 14:09:35,258 DEBUG (Wire.java:73)- http-outgoing-0 >> "Host: www.baidu.com[\r][\n]"
26 main 2021-02-09 14:09:35,258 DEBUG (Wire.java:73)- http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
27 main 2021-02-09 14:09:35,258 DEBUG (Wire.java:73)- http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.12 (Java/1.8.0_161)[\r][\n]"
28 main 2021-02-09 14:09:35,258 DEBUG (Wire.java:73)- http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
29 main 2021-02-09 14:09:35,258 DEBUG (Wire.java:73)- http-outgoing-0 >> "[\r][\n]"
30 main 2021-02-09 14:09:35,300 DEBUG (Wire.java:73)- http-outgoing-0 << "HTTP/1.1 200 OK[\r][\n]"
31 main 2021-02-09 14:09:35,301 DEBUG (Wire.java:73)- http-outgoing-0 << "Content-Encoding: gzip[\r][\n]"
32 main 2021-02-09 14:09:35,301 DEBUG (Wire.java:73)- http-outgoing-0 << "Content-Length: 1145[\r][\n]"
33 main 2021-02-09 14:09:35,301 DEBUG (Wire.java:73)- http-outgoing-0 << "Content-Type: text/html[\r][\n]"
34 main 2021-02-09 14:09:35,301 DEBUG (Wire.java:73)- http-outgoing-0 << "Server: bfe[\r][\n]"
35 main 2021-02-09 14:09:35,301 DEBUG (Wire.java:73)- http-outgoing-0 << "Date: Tue, 09 Feb 2021 06:09:34 GMT[\r][\n]"
36 main 2021-02-09 14:09:35,302 DEBUG (Wire.java:73)- http-outgoing-0 << "[\r][\n]"
37 main 2021-02-09 14:09:35,302 DEBUG (Wire.java:73)- http-outgoing-0 << "[0x1f][0x8b][0x8][0x0][0x0][0x0][0x0][0x0][0x0][0xff][0x94]V[[0x8f][0xd4][0xb6][0x17]G[0xe2];[0x98][0xfc][0xb5][0xbb] 4[0xe3][0xb9][0x8][0xc1]7[0x9][0xda]nABH[0x5][0x15]V*O#[0xc7]v[0x12][0xb3][0x89]mlg[0xc2][0xf0][0xd4][0x95]J[0xd5][0xaa][0xa5][0xb4][0xa2][0x17]Q*[0xb5][0xaa]Z[0xb6][0xf][0x95][0xa0]*R[0xd1]R[0xe0][0xcb]L[0xd8][0xdd][0xa7]~[0x85][0xca]If[0xe7][\n]"
38 main 2021-02-09 14:09:35,302 DEBUG (Wire.java:73)- http-outgoing-0 << "[0xa8][0xf3][0x12][0xfb][0xf8][0x9c][0xdf][0xf9][0x9d][0x9b]=[0xee][0xb1]w/m\[0xbd]v[0xf9][0x1c][0x88]M[0x9a][0xf8]G[0x8f][0xb8][0xc7][0x1a][0x8d]+W[0xd7][0xaf]n^[0x1][0x97].6[0x1a][0xbe][[0xca][0x81][0x1b]SD|7[0xa5][0x6][0x81][0xd8][0x18][0xd9][0xa0]72[0xd6][0xf7][0xb0][0xe0][0x86]r[0xd3]0[0x3]IA[0xbd][0xf1][0xc][0xbd]i[0xa0]5[[0xc3]1R[0x9a][0x1a]/3a[0xe3][0xcc][0xbc][0xf5][0x7][0x8d][0xcd][0xf5][0xc6][0x86]H%2,H[0xc6][0x0][0x17][0xce]y[0xe7]HDk[0x83][0x91][0x14]%9[0x1a]h[0xc0]QJ=EC[0xaa][0x14]U[0xbe][0x9b]0[0xbe][0x5][0x14]M<m[0x6][0x9][0xd5]1[0xa5][0x6]X6[0x15][0xb][0xac]5[0x88][0x15][\r]=[0xeb]U[0xaf]B[0xa8]u[0xbb][0x19][0x10]m[0x90]a[0xb8][0x89]E[\n]"
39 main 2021-02-09 14:09:35,302 DEBUG (Wire.java:73)- http-outgoing-0 << "O[0xd1][0xf7][0xda][0xc1][0xf5][0x1b]g[0xd6][0xd7]7[0xaf][0xa5][0x9d][[0x91][0xb8][0xd6][0xbd][0x8][0x15][0xcc][0xf3][0x1c]b[0x84]c[\n]"
40 main 2021-02-09 14:09:35,302 DEBUG (Wire.java:73)- http-outgoing-0 << "[0x3]"[0xd4]-[0x18] F[0xb2]f[0xca]x[0x13]k[0xed][0xbb][0x86][0x99][0x84][0xfa]{[0xf7]_[0x14][0xbb][0xf][0x87]O?[0x1c]>[0xfd][0xec][0x9f][0xbf]?[0x1f]>[0xff][0xa9]x[0xfc][0xc7][0xde][0x8f][0xbf][0x1e]l[0xdf]sa[0xa5][0xe2][0xc2]2q[0xc0][\r][0x4][0x19][0x0]K[0xd6][0xfb]_[0xab][0xd5]ja[0xec][0x3][0x97][0xb0]>`[0xc4][0xcb][0x15][0x92][0x92][0xaa][0xb1][0xa0]6[0xb1];[0x9c] [0xad]KAoZ[0xad]:[0xd0][0xbd]P[0xa8]t[0x81][0xa8]7[0x7][0x9a]D>pY[0x1a][0x81][0x98][0x11][0x1a][\n]"
41 main 2021-02-09 14:09:35,303 DEBUG (Wire.java:73)- http-outgoing-0 << "[0x9c]i[0xcf][0xa8][0x8c][0x2][0xad][0xb0][0x7]m[0xbc][0xcd]*F[0x9b][0x14][0x96]F0 [0xbd]DD[0xa2][0xdd][0x94]<[0x2]9#&[0xf6]:[0xa7][ [0xa6],[0x8a][0x8d][0xd7][0xee][0xfc][0xdf][0x7].$[0xac][0xef][0x3][0xd7]:[0xb4].[0xca]oY[0x9f][0x10] l[0x98][0xe0]s[0xc8][0xba]f[0x19]Z[0xd2][0x8c][0xcb][0xac][0xae]V[0xcc][0x8][0xa1][0xbc]2.3[0xde][0xc3]"[0xa5][0xa0][0x8f][0x92][0x8c]z[0xed][0xd7][0xeb][0xb2][0x91]N[0xd5]b[0xaf][0xd5][0xb]k[0xb5]7[0xa8]([0xdd][0xef][0x5][0xf2][0xed].[0xad][0x1e]#7[0xdf][0xae]hx[0xad]S[0x86][0xef][0xbb]Z"^[0x87][0xef][0x4][0x11][0xd0]=&M/W[0x8e]_[0x3]0[0xe2]m[0xe5][0x95]iN[0xe][0xab][0xc9][0xa4][0xa9]`@[0x8a]n&[0x94]G[0xb6][0x10][0xa7]N[0x1][0x94][0x19][0x81]E*[0x13]j[0xa8]'[0xc2][0xb0][0x14]Tu=\[0xf9].[0xb4]N[0x17][0xb8][0xe][0xc][0x9f]t]r[0xd7]Y[0x90][0xb2][0x92][0x86][0xce]j[0xe6][0x93][0x1d]>k[0xef][0x80]9?[0xc0][0x85]u?[0xd6][0x9d]Q[0xea][0x16][0xcc]l[0xb2][0xd0]x W![0xe4]4[0xd7][0xe3][0xf6][0xa8][0xf3]v[0xbd]g[0x94]=[0xa8]=[0xa6][0x1c][0xf5][0xfd]W[0xdf]>>[0xf8][0xee][0x99][0xb][0xd1]4[0x84][0x9d]i[0xdb]a1[0x12][0xed]Nw[0x6][0xa3][0x12]N[0xa2]T[0x92]9[0x94]U[0x8]S$[0x17][0xf2]H[0x91][0x9c][0x4](~x\<x[0xb1][0x8][0xa0][0xbf][0xd0][0xbc][0xcf][0x8][0x15][0x93][0x0][0xfb];[0x1f][0x1f][0xfc][0xfc][0xd5]"[0x0][0xc3]h[0x80][0x16][0x82][0x94]'S O[0x9e][0x14]_[0xee]T \h[0xac][0x98]4sx[0xd3][0x83]W]c[0x89][0x88][0x18]oF,<[[0xae][0x96]Q*[0xd7][0x8c]L[0xbc][0xb4]Zf[0xa5][0xed]Rw}[0xa9]s~[0xa9]s~[\n]"
42 main 2021-02-09 14:09:35,303 DEBUG (Wire.java:73)- http-outgoing-0 << "a[0xa9][0x13].u[0xc3][0xf1]l.uI[0xfb][0x90]c[0x89]V3L[0x2][0xef][0xfe][0xb3][0xe2][0xf9]7[0x15]?8A[0xb0]^[0x10][0x81][0xb3][0x94]r[0xd3][0xcc][0x15]3[0xf4][0xf8][0xca][0x88][0xb8][0xf3][0x1f][0x98][0xd7][0xac]3o[0xe5]$[0xa0][0x1c][0xb]B7[0xdf][0xbf]`[0xdf][0x12][0xc1])7[0xc7]s[0xc6][0x89][0xc8][0x9b][0x89][0xc0][0xc8][0xde]CM[0x8b][0x12][0xcc][0x89]5E[\n]"
43 main 2021-02-09 14:09:35,303 DEBUG (Wire.java:73)- http-outgoing-0 << "[0xc7][0xc0][0xf3]<[0xe0]8[0xe0],p[0xce]:`[0x15]8[0xcb][0xce][0x89][0x93][0xc0][0x19][0xc7][0xea][0xb5][0xad]`[0xc5][0xa9][0xe2]uF[0x1];[0xa3][0x91]H[0x2]g"[0xe6][0x95][0x13]kG[0x8f][0x80][0x99][0x9f][0xb]g[0xcb]4[0x1b]g*[0x14][0x85][0x87][0x19][\r][0x14]cX[0x8c]r[0x1a]([0x6][0xca][0x7][0xce]s[0x8][0xd3]2A[0x83]U[0x10]$[0x2]o[0xad]9[0xfe][0xab][0x7]O[0x8a]_[0xbe][0x1f][0xee][0xee][0x14][0xf7][0xb6][0xeb][0x94]O[\r][0xdf][0xf4][0xc][0x86]fC[0xf0][0x99]m[0xee][0x3]W[0x96]oD<[0xd7]E[0xb1]H[0xe9][0x98][0xa4]_[0xdc][0xfe]s[0xb8][0xfb]Eu-,jb[0xa6]&[0x94][0xd7][0x3][0x91][0x19][0xf0][0x8e][0xdd][0xd7][0xc4][0xe4][0xc8][0x13][0x96][0xfe]2[0x16]r[0xb0][0xd6]i[0xb5]O/[0xf3]@[0xcb][0xb5]R[0xaf]Z[0xbe][0xb1][0x93]If[0x6][0xd0][0x1f]>[0xb9][0xf7][0xf5]o[0x15][0x91][0xe2][0xd3];[0xc5][0xcb][0xdb][0xfb][0x8f][0xca][0xeb][0xa1]B[0x98][0xe5]u[0x9d]!>`[0x13](ub[0xb1]l[0x84][0x94][0x92][0x0][0xe1]-[0xff][0xd5]Gw[0xf7]w[0xb6][0x8b][0xbb]w[0xe][0x1e]~2F[0x1a][0xee][0xfe]~a[0xe3][0xf2][0xfe][0xa3][0xed]V[0xb7][0xd5]>[0xdd]-[0xee][0xfe]5[0xf2]`[0x1f][0xd3][0xd7][0xbd][0x9e][0x91][0xb6][0xbd]:[\n]"
44 main 2021-02-09 14:09:35,303 DEBUG (Wire.java:87)- http-outgoing-0 << "yaA[0xa0][0xfd]K`[0xbf][0xf5]?[0xaf][0x3][0x0][0x0][0xff][0xff]0[0xc][0x81][0x9a][0x8b][0x9][0x0][0x0]"
45 main 2021-02-09 14:09:35,306 DEBUG (LoggingManagedHttpClientConnection.java:122)- http-outgoing-0 << HTTP/1.1 200 OK
46 main 2021-02-09 14:09:35,306 DEBUG (LoggingManagedHttpClientConnection.java:125)- http-outgoing-0 << Content-Encoding: gzip
47 main 2021-02-09 14:09:35,306 DEBUG (LoggingManagedHttpClientConnection.java:125)- http-outgoing-0 << Content-Length: 1145
48 main 2021-02-09 14:09:35,306 DEBUG (LoggingManagedHttpClientConnection.java:125)- http-outgoing-0 << Content-Type: text/html
49 main 2021-02-09 14:09:35,306 DEBUG (LoggingManagedHttpClientConnection.java:125)- http-outgoing-0 << Server: bfe
50 main 2021-02-09 14:09:35,306 DEBUG (LoggingManagedHttpClientConnection.java:125)- http-outgoing-0 << Date: Tue, 09 Feb 2021 06:09:34 GMT
51 main 2021-02-09 14:09:35,310 DEBUG (MainClientExec.java:285)- Connection can be kept alive indefinitely
52 main 2021-02-09 14:09:35,316 DEBUG (HttpClientProviderImpl.java:46)- respString: <!DOCTYPE html>
53 <!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn" autofocus></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');
54 </script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>使用百度前必读</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173号&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
55 main 2021-02-09 14:09:35,318 DEBUG (PoolingHttpClientConnectionManager.java:344)- Connection [id: 0][route: {s}->https://www.baidu.com:443] can be kept alive indefinitely
56 main 2021-02-09 14:09:35,318 DEBUG (LoggingManagedHttpClientConnection.java:88)- http-outgoing-0: set socket timeout to 0
57 main 2021-02-09 14:09:35,318 DEBUG (PoolingHttpClientConnectionManager.java:351)- Connection released: [id: 0][route: {s}->https://www.baidu.com:443][total available: 1; route allocated: 1 of 50; total allocated: 1 of 200]
58 main 2021-02-09 14:09:35,319 WARN (HttpClientServiceTest.java:80)- requestGet, times: 0, betMils: 403,betNanos: 402522300

httpClientLog

2. 综合比较

  maxTotal:200

Threads

defaultMaxPerRoute

validateAfterInactivity

betMils

betNanos

256

20

1500

5270

5269994599

50

4310

4310753100

100

4513

4512503700

150

4963

4962632601

200

5245

5244764201

1024

20

1500

5087

5087564601

50

4323

4323088301

64

50

15000

3900

3900514800

2000(default)

3531

3537111900

0

3358

3355394500

32

50

0

3471

3456438200

2000(default)

2918

2912550800

50

50

15000

2847

2846675400

0

3190

3189325400

2000(default)

3263

3264044800

1000

2741

2740233600

500

2802

2801841600

800

2800

2800641400

  

  根据以上数据我们能看出什么呢?

  在分析数据以前我先罗列一下电脑配置:

  Windows 10 专业版

  Intel(R) Core(TM) i5-7400 CPU @ 3.00GHz 3.00 GHz 4核

  16.0 GB

  64 位

  SSD 232.89 GB

  首先根据本机硬件及系统配置,多线程可以提高系统的并发效率,但是也不是绝对的,大致在50个线程的时候效果较好。然后defaultMaxPerRoute参数也是50,即每个路由默认并行接受的请求数。因为本文的测试目标服务器是百度,百度服务器设置连接时间可无限期的保持“Connection can be kept alive indefinitely”,调节validateAfterInactivity参数,总的来说效果不是很大,当然需要排除网络请求的一些影响因素,比如拥塞、路由等情况,可根据下表的参数比较知道,即使相同的配置参数,不同时间点请求服务器,响应的时长也有差异,也就是说每一次的网络请求都是必然中的一次偶然情况。

3. 同参数比较

  Threads: 50

  maxTotal: 200

  defaultMaxPerRoute:50

  validateAfterInactivity:1000

  idleTimeOut:3

betMils

betNanos

2813

2813779600

3228

3229129100

3030

3030484200

2806

2805046900

2981

2981383600

2629

2629455200

2814

2813863100

2747

2747754700

2748

2747132800

3365

3365044500

  通过上表可以看出,每一次网络请求在同一网络情况下或相似网络情况下,响应的时长差距不大。但因为影响网络的因素众多,导致每次响应的时长都不一样。

四、后记

  暂时先分享到此,后期会有补充的,比如源码、架构等。

HttpClient客户端网络编程——高可用、高并发的更多相关文章

  1. 在CentOS上使用Nginx和Tomcat搭建高可用高并发网站

    目录 目录 前言 创建CentOS虚拟机 安装Nginx 安装Tomcat 安装lvs和keepalived 反向代理 部署网站 搭建数据库 编写网站项目 解决session一致性 注意 参考资料 前 ...

  2. PHP开发高可用高安全App后端☆

    第1章 本章先讲解课程所含技术点,并演示相关的项目,让小伙伴对课程有个初步的认知,然后再带领小伙伴进行功能的分析,表的ER总关系图 第2章本章主要讲解课程的一些准备工作知识.包括工具.环境.模板等. ...

  3. PHP开发 高可用 高安全App后端(免费)

    PHP开发高可用高安全App后端 第1章 本章先讲解课程所含技术点,并演示相关的项目,让小伙伴对课程有个初步的认知,然后再带领小伙伴进行功能的分析,表的ER总关系图 第2章 本章主要讲解课程的一些准备 ...

  4. 人人都可以开发高可用高伸缩应用——论Azure Service Fabric的意义

    今天推荐的文章其实是微软的一篇官方公告,宣布其即将发布的一个支撑高可用高伸缩云服务的框架--Azure Service Fabric. 前两天,微软Azure平台的CTO Mark Russinovi ...

  5. (转)mysql数据库高可用高扩展性架构方案实施

    http://shanhu.blog.51cto.com/1293405/1212605-----mysql数据库高可用高扩展性架构方案实施

  6. 面试中的nginx高可用高并发!

    本文转自:91博客:原文地址:http://www.9191boke.com/439923471.html 面试题: nginx高可用?nginx 是如何实现并发的?为什么nginx不使用多线程?ng ...

  7. 做了两年java,这些高性能高可用高并发的技术架构你都知道吗?

    前言 每一个模式描述了一个在我们周围不断重复发生的问题及该问题解决方案的核心.这样,你就能一次又一次地使用该方案而不必做重复工作. 所谓网站架构模式即为了解决大型网站面临的高并发访问.海量数据.高可靠 ...

  8. keepalived+LVS 实现双机热备、负载均衡、失效转移 高性能 高可用 高伸缩性 服务器集群

    本章笔者亲自动手,使用LVS技术实现实现一个可以支持庞大访问量.高可用性.高伸缩性的服务器集群 在读本章之前,可能有不少读者尚未使用该技术,或者部分读者使用Nginx实现应用层的负载均衡.这里大家都可 ...

  9. UNIX网络编程——select函数的并发限制和 poll 函数应用举例

    一.用select实现的并发服务器,能达到的并发数,受两方面限制 1.一个进程能打开的最大文件描述符限制.这可以通过调整内核参数.可以通过ulimit -n来调整或者使用setrlimit函数设置,  ...

随机推荐

  1. 【ORACLE】11g rac+dg

    首先感谢群友分享的文档,在这里先感谢哆啦B梦,非常感谢 该文档主要指导如何利用现有的RAC环境搭建一套RAC与单实例的DG的环境  ============================主机配置信息 ...

  2. 攻防世界 - Misc(一)

    base64÷4: 1.下载附件,是一个.txt文件,打开是一串字符, 666C61677B453333423746443841334238343143413936393945444442413234 ...

  3. centos7安装宝塔面板

    在终端下执行如下命令 yum install -y wget && wget -O install.sh http://download.bt.cn/install/install.s ...

  4. CodeMonkey少儿编程第3章 times循环

    目标 了解程序由哪三种基本的结构组成 了解循环的概念 掌握times的结构与用法 三种基本结构 计算机程序由三种最基本的结构组成,它们分别是: 顺序结构 循环结构 选择结构 千万不要被这些陌生的术语给 ...

  5. MVC和MTV框架模式

    1. MVC: MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller ...

  6. 开心!再也不用担心 IntelliJ IDEA 试用过期了

    背景 前段时间 Review 团队小伙伴代码,发现当他把鼠标挪到一个方法上时,就自动显示了该方法的所有注释信息,像下图这样,他和我用的 IDE 都是 IntelliJ IDEA. 而我还按古老的方式, ...

  7. QUIC协议分析-基于quic-go

    quic协议分析 QUIC是由谷歌设计的一种基于UDP的传输层网络协议,并且已经成为IETF草案.HTTP/3就是基于QUIC协议的.QUIC只是一个协议,可以通过多种方法来实现,目前常见的实现有Go ...

  8. 研发流程 接口定义&开发&前后端联调 线上日志观察 模型变动

    阿里等大厂的研发流程,进去前先了解一下_我们一起进大厂 - SegmentFault 思否 https://segmentfault.com/a/1190000021831640 接口定义 测试用例评 ...

  9. Language Guide (proto3) | proto3 语言指南(开篇)

    前言 近日在学习gRPC框架的相关知识时接触到Protobuf(protocol-buffers,协议缓冲区),proto3等知识.网上很多文章/帖子经常把gRPC与proto3放在一起,为避免初学者 ...

  10. 如何使用Conda源快速安装PyTorch?

    数据科学交流群,群号:189158789,欢迎各位对数据科学感兴趣的小伙伴的加入! 1.切换国内源 1.1.在家目录生成.condarc conda config --set show_channel ...