关于JDK自身的HttpURLConnection
在底层是否复用socket的测试方式,可以快速用repl和lsof来检测:
// 本地启动一个 http server,它返回十几个字符
➜ curl "http://localhost:8080/sleep?time=1000"
{"code":"ok"}
// 在repl下连续请求这个url 若干次
scala> val is = new java.net.URL("http://localhost:8080/sleep?time=100").openConnection.getInputStream; for(i <- 1 to 15) is.read; is.close
is: java.io.InputStream = sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@1ba9117e
scala> val is = new java.net.URL("http://localhost:8080/sleep?time=100").openConnection.getInputStream; for(i <- 1 to 15) is.read; is.close
is: java.io.InputStream = sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@a82c5f1
与此同时在另一个终端用lsof查看socket,每秒刷新一次,可看到客户端socket是同一个
➜ /usr/sbin/lsof -Pan -iTCP -r 1 -p 43280
=======
=======
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 43280 hongjiang 47u IPv6 0x43acdfd2ea5b0c01 0t0 TCP 127.0.0.1:57304->127.0.0.1:8080 (ESTABLISHED)
=======
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 43280 hongjiang 47u IPv6 0x43acdfd2ea5b0c01 0t0 TCP 127.0.0.1:57304->127.0.0.1:8080 (ESTABLISHED)
=======
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 43280 hongjiang 47u IPv6 0x43acdfd2ea5b0c01 0t0 TCP 127.0.0.1:57304->127.0.0.1:8080 (ESTABLISHED)
=======
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 43280 hongjiang 47u IPv6 0x43acdfd2ea5b0c01 0t0 TCP 127.0.0.1:57304->127.0.0.1:8080 (ESTABLISHED)
这个话题是由URLConnection
在关闭的时候应该调用close
还是disConnect
所引起的,关于jdk里keep-alive相关的一些参数不展开了。
验证disconnect
方法:
// 执行若干次
scala> val conn = new java.net.URL("http://localhost:8080/sleep?time=100").openConnection.asInstanceOf[java.net.HttpURLConnection]; val is=conn.getInputStream; for(i <- 1 to 15) is.read; conn.disconnect
这时没法用lsof观察了,它最小刷新单位是1秒,因为每次连接立即关闭导致没机会看到,得用tcpdump来观察
➜ sudo tcpdump -i lo0 -s 1024 -l -A port 8080
^[[A04:59:57.066577 IP localhost.57355 > localhost.http-alt: Flags [S]
...
-`=.-`=.GET /sleep?time=100 HTTP/1.1
User-Agent: Java/1.8.0_51
Host: localhost:8080
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
...
05:00:05.407691 IP localhost.57356 > localhost.http-alt: Flags [P.], seq 1:168, ack 1, win 12759, options [nop,nop,TS val 761290281 ecr 761290281], length 167: HTTP: GET /sleep?time=100 HTTP/1.1
E...LF@.@.........................1........
-`^)-`^)GET /sleep?time=100 HTTP/1.1
User-Agent: Java/1.8.0_51
Host: localhost:8080
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
...
05:00:07.045830 IP localhost.57357 > localhost.http-alt: Flags [P.], seq 1:168, ack 1, win 12759, options [nop,nop,TS val 761291915 ecr 761291915], length 167: HTTP: GET /sleep?time=100 HTTP/1.1
E.....@.@................l.;.\.,..1........
-`d.-`d.GET /sleep?time=100 HTTP/1.1
User-Agent: Java/1.8.0_51
Host: localhost:8080
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
看到三次连接每次客户端socket端口都变了。