依赖

  1. OkHttp
1
2
3
4
5
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>
  1. apache httpclient
1
2
3
4
5
6
7
8
9
10
11
12
<!--同步请求模块-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
<!--异步请求模块-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpasyncclient</artifactId>
<version>4.1.5</version>
</dependency>

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
public class HttpClient {


static List<String> urlList = new ArrayList<>();

static {
Logger logger = (Logger) LoggerFactory.getLogger("org.apache.http");
// 设置日志级别为OFF
logger.setLevel(Level.OFF);
for (int i = 0; i < 100; i++) {
urlList.add("http://127.0.0.1:8080/query");
}
}

public static void main(String[] args) throws IOException, InterruptedException {

// okHttpSync();

// okHttpAsync();

// apacheHttpSync();

// apacheHttpAsync();

}

public static OkHttpClient okHttpClient() {
Dispatcher dispatcher = new Dispatcher();
//maxRequests和maxRequestsPerHost是同时能够请求的数量,底层通过两个队列存储,但是只会计算异步请求的数量,不过异步请求占满了之后同步请求也会被拒绝
dispatcher.setMaxRequests(20);
dispatcher.setMaxRequestsPerHost(10);//maxRequestsPerHost记录同ip的请求
//okhttp连接池底层是链表,所以大小没有限制,底层也没有提供最大连接数,只提供了,最大空闲连接以及最大空闲时间
ConnectionPool connectionPool = new ConnectionPool(10, 10, TimeUnit.SECONDS);
return new OkHttpClient().newBuilder().connectionPool(connectionPool).dispatcher(dispatcher).build();
}

public static void okHttpSync() {
OkHttpClient client = okHttpClient();

/**
* 同步请求 底层使用Socket
*/

AtomicInteger i = new AtomicInteger();
ExecutorService executorService = Executors.newCachedThreadPool();
CountDownLatch countDownLatch = new CountDownLatch(100);
for (String url : urlList) {
executorService.execute(() -> {
Request request = new Request.Builder()
.url(url)
.build();
try {
Response response = client.newCall(request).execute();
System.out.println(response.body().string() + "----" + i.getAndIncrement());
countDownLatch.countDown();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
executorService.shutdown();
try {
countDownLatch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

public static void okHttpAsync() {
OkHttpClient client = okHttpClient();

/**
* 异步请求 底层使用Socket,原理是将请求作为任务保存到队列,交给专门处理异步请求的线程处理请求,请求完成后调用回调函数,
* 异步请求底层使用的是缓存线程池,即同时有多少异步请求,就同时创建多少线程
*/
urlList.forEach(url -> {
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
System.out.println("请求失败");
}

@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
System.out.println(response.body().string());
}
});
});
}

public static void apacheHttpSync() {

/**
* maxConnTotal是最大连接数,和okhttp不同,apache httpclient连接数是可以设置的,底层使用的也是链表,defaultSocketConfig是路由最大连接数,
* 这里的路由是具体到端口的,而okhttp只会到ip
*/
CloseableHttpClient httpclient = HttpClients.custom().setMaxConnTotal(20).setMaxConnPerRoute(20).build();
AtomicInteger i = new AtomicInteger();
ExecutorService executorService = Executors.newCachedThreadPool();
CountDownLatch countDownLatch = new CountDownLatch(urlList.size());
urlList.forEach(url -> {
executorService.execute(() -> {
try {
CloseableHttpResponse response = httpclient.execute(new HttpGet(url));
System.out.println(IoUtil.readUtf8(response.getEntity().getContent()) + "----" + i.getAndIncrement());
response.close();
countDownLatch.countDown();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
});
executorService.shutdown();
try {
countDownLatch.await();
httpclient.close();
} catch (InterruptedException | IOException e) {
throw new RuntimeException(e);
}

}

public static void apacheHttpAsync() {

/**
* 底层使用NIO,所以不受线程的限制,数据会先写入到conn.getContext().getAttribute(HTTP_HANDLER)中(org.apache.http.impl.nio.client.AbstractClientExchangeHandler),conn为httpclient异步请求自定义的连接,底层有一个IOReactor的类,
* 会调用系统方法获取那些channel是可以写入的,然后访问连接的SessionOutputBufferImpl,如果有数据,则直接写入channel,发送给服务端,如果没有数据,则将conn.getContext().getAttribute(HTTP_HANDLER)
* 中的数据写入然后访问SessionOutputBufferImpl中,然后进行发送,虽然异步请求不受线程多少影响,但是这里用到了多线程,IOReactor有一个AbstractMultiworkerIOReactor实现类,
* 它会创建多个(电脑cpu核数)线程,每个线程都有一个独立的IOReactor并行处理数据
*/
CloseableHttpAsyncClient asyncClient = HttpAsyncClients.custom().setMaxConnTotal(20).setMaxConnPerRoute(20).build();
asyncClient.start();

AtomicInteger i = new AtomicInteger();
for (String url : urlList) {
asyncClient.execute(new HttpGet(url), new FutureCallback<HttpResponse>() {
@Override
public void completed(HttpResponse httpResponse) {
try {
System.out.println(IoUtil.readUtf8(httpResponse.getEntity().getContent()) + "----" + i.getAndIncrement());
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
public void failed(Exception e) {

}

@Override
public void cancelled() {

}
});
}

}

}

本站总访问量:次本站总访问数:人
本站由 Peng Tong 使用 Stellar 1.29.1 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。