我想要拿出一個簡單的HTTP客戶端的Java實現,它保持套接字打開並重用它來查詢同一主機上的其他(或相同)URL 。Java套接字保持活着很慢,重新打開套接字更快
我有一個簡單的實現,使用java.net.Socket,但不知何故,當我保持打開套接字的性能比當我不斷創建一個新的更糟糕。
結果第一,低於全可執行代碼:
成KeepAlive:
> java -server -Xms100M -Xmx100M -cp . KeepAlive 10 false
--- Warm up ---
188
34
39
33
33
33
33
33
34
33
Total exec time: 494
--- Run ---
33
35
33
34
44
34
33
34
32
34
Total exec time: 346
保持活動:在迭代#2
> java -server -Xms100M -Xmx100M -cp . KeepAlive 10 true
--- Warm up ---
18
61
60
60
78
62
59
60
59
60
Total exec time: 626
--- Run ---
26
59
60
61
60
59
60
60
62
58
Total exec time: 576
重塑插座每次提供更好的結果,從慢。 java(獨立,無依賴)
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
public class KeepAlive {
private static final String NL = "\r\n";
private static final int READ_SIZE = 1000;
private Socket socket;
private DataOutputStream writer;
private BufferedReader reader;
public static void main(String[] args) throws Exception {
if (args.length == 2) {
KeepAlive ka = new KeepAlive();
System.out.println("--- Warm up ---");
ka.query(Integer.parseInt(args[0]), args[1].equals("true"));
System.out.println("--- Run ---");
ka.query(Integer.parseInt(args[0]), args[1].equals("true"));
} else {
System.out.println("Usage: keepAlive <n queries> <reuse socket>");
}
}
private void query(int n, boolean reuseConnection) throws Exception {
long t0 = System.currentTimeMillis();
if (reuseConnection) {
open();
for (int i = 0; i < n; i++) {
long tq0 = System.currentTimeMillis();
query();
System.out.println(System.currentTimeMillis() - tq0);
}
close();
} else {
for (int i = 0; i < n; i++) {
long tq0 = System.currentTimeMillis();
open();
query();
close();
System.out.println(System.currentTimeMillis() - tq0);
}
}
System.out.println("Total exec time: " + (System.currentTimeMillis() - t0));
}
private void open() throws Exception {
socket = new Socket();
socket.setKeepAlive(false);
socket.connect(new InetSocketAddress("example.org", 80));
writer = new DataOutputStream(socket.getOutputStream());
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
private void query() throws Exception {
StringBuilder req = new StringBuilder();
req.append("GET/HTTP/1.1").append(NL);
req.append("Host: example.org").append(NL);
req.append("Connection: Keep-Alive").append(NL);
req.append(NL);
String reqStr = req.toString();
long t0 = System.currentTimeMillis();
writer.writeBytes(reqStr);
writer.flush();
String line;
int contentLength = 0;
while ((line = reader.readLine()) != null) {
if (line.startsWith("Content-Length: ")) {
contentLength = Integer.parseInt(line.substring(16));
}
if (line.equals("")) {
char[] buf = new char[contentLength];
int offset = 0;
while (offset < contentLength) {
int len = contentLength - offset;
if (len > READ_SIZE) {
len = READ_SIZE;
}
int ret = reader.read(buf, offset, len);
if (ret == -1) {
System.out.println("End of stream. Exiting");
System.exit(1);
}
offset += ret;
}
break;
}
}
}
private void close() throws Exception {
writer.close();
reader.close();
socket.close();
}
}
現在,我敢肯定,無論是:
Web服務器在處理快速的新要求很爛(HTTP Keep Alive and TCP keep alive)
東西是錯誤的我用的是緩衝讀者,因爲路這就是所有的時間都失去了,但看着其他可用的方法(和我嘗試了一些),我無法找到我需要做什麼來解決這個問題......我
任何想法,怎麼可能做這個w ork更快?也許一個配置更改服務器本身?上...
解決方案
由於apangin下面解釋由越慢PERF是Nagle算法,它是默認啓用造成的。 使用setTcpNoDelay(真),我得到了更新以下perfs:
不保活:
java -server -Xms100M -Xmx100M -cp . KeepAlive 10 false
--- Warm up ---
49
22
25
23
23
22
23
23
28
28
Total exec time: 267
--- Run ---
31
23
23
24
25
22
23
25
33
23
Total exec time: 252
隨着保活:
java -server -Xms100M -Xmx100M -cp . KeepAlive 10 true
--- Warm up ---
13
12
12
14
11
12
13
12
11
12
Total exec time: 168
--- Run ---
14
12
11
12
11
12
13
11
21
28
Total exec time: 158
所以在這裏,我們可以看到保對於每次迭代,如果比較總執行時間,動態版本的執行效率會比非保持活動版本要好得多。 :)
你並不是真的像這裏一樣測試。在一個你正在儘可能努力地錘擊服務器。另一方面,你會在每個查詢之間暫停一下。您是否嘗試過每次運行測試客戶端的總時間? – BevynQ
是的,這就是測試的重點:看看兩種不同行爲中哪一種表現最好。問題在於:「我能以多快的速度提出請求並獲得響應,無論是否保持活力」。我爲你添加了總執行時間。 – fabien