HttpClient客户端网络编程——高可用、高并发

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

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

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

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

一、本文目录

  1. 代码实现

  2. 测试验证

  3. 后记

二、代码实现

1. 项目依赖

HttpClient客户端网络编程——高可用、高并发HttpClient客户端网络编程——高可用、高并发
 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. 项目结构

  HttpClient客户端网络编程——高可用、高并发

3. 项目配置

HttpClient客户端网络编程——高可用、高并发HttpClient客户端网络编程——高可用、高并发
 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可以在连接池处于闲暇时进行收缩,不过网络上资料较少,目前还没研究出怎么使用和配置。

HttpClient客户端网络编程——高可用、高并发HttpClient客户端网络编程——高可用、高并发
  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工具类

HttpClient客户端网络编程——高可用、高并发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业务接口及其实现

HttpClient客户端网络编程——高可用、高并发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

HttpClient客户端网络编程——高可用、高并发HttpClient客户端网络编程——高可用、高并发
 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的接口,丝毫不会受到影响。所以编程原则里有一条:面向接口编程,面向抽象编程。

HttpClient客户端网络编程——高可用、高并发HttpClient客户端网络编程——高可用、高并发
 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

HttpClient客户端网络编程——高可用、高并发HttpClient客户端网络编程——高可用、高并发
 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业务接口测试

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

HttpClient客户端网络编程——高可用、高并发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. 运行日志

HttpClient客户端网络编程——高可用、高并发HttpClient客户端网络编程——高可用、高并发
 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

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

四、后记

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

上一篇:3.3 用NPOI操作EXCEL--生成一张工资单


下一篇:Winform开发中的困境及解决方案