gpt4 book ai didi

java - 爬虫为某些服务器留下大量 ESTABLISHED TCP 套接字

转载 作者:行者123 更新时间:2023-11-29 09:23:14 25 4
gpt4 key购买 nike

我有一个 Java 网络爬虫。我注意到,对于我抓取的少量服务器,我留下了大量已建立的套接字:

joel@bohr:~/tmp/test$ lsof -p 6760 | grep TCP 
java 6760 joel 105u IPv6 96546 0t0 TCP bohr:55602->174.143.223.193:www (ESTABLISHED)
java 6760 joel 109u IPv6 96574 0t0 TCP bohr:55623->174.143.223.193:www (ESTABLISHED)
java 6760 joel 110u IPv6 96622 0t0 TCP bohr:55644->174.143.223.193:www (ESTABLISHED)
java 6760 joel 111u IPv6 96674 0t0 TCP bohr:55665->174.143.223.193:www (ESTABLISHED)

任何一台服务器都可能有几十个这样的东西,我不明白为什么它们被打开了。

我正在使用 HttpURLConnection 建立连接并读取数据。 HTTP 1.1 和 keep-alive 开启(默认)。据我了解,Java 的 HttpURLConnection 将重新使用远程服务器的底层 tcp 套接字,只要我关闭输入/错误流,并从流中读取所有数据。这也是我的理解,如果抛出异常,那么只要输入/错误流关闭(如果不是 null),那么套接字虽然不会再次使用,但也会关闭。 ( java handling of http-keepalive )

我的缩写代码如下所示:

  InputStream is = null;
try {
HttpURLConnection conn = (HttpURLConnection) uri.toURL().openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(10000);
conn.setRequestProperty("User-Agent", userAgent);
conn.setRequestProperty("Accept", "text/html,text/xml,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
conn.setRequestProperty("Accept-Encoding", "gzip deflate");
conn.setRequestProperty("Accept-Language", "en-gb,en;q=0.5");
conn.connect();

try {
int responseCode = conn.getResponseCode();
is = conn.getInputStream();

} catch (IOException e) {
is = conn.getErrorStream();
if (is != null){
// consume the error stream, http://download.oracle.com/javase/6/docs/technotes/guides/net/http-keepalive.html
StreamUtils.readStreamToBytes(is, -1 , MAX_LN);
}
throw e;
}

String type = conn.getContentType();

byte[] response = StreamUtils.readStream(is);
// do something with content


} catch (Exception e) {
conn.disconnect(); // don't try to re-use socket - just be done with it.
throw e;

} finally {
if (is != null) {
is.close();
}
}

我注意到对于发生这种情况的网站,我在发出 GET 请求时会抛出很多 IOExceptions,原因是:

java.net.ProtocolException: Server redirected too many  times (20)

我很确定我正在处理这个问题,正确关闭套接字。真的是这个,还是我做错了什么?这可能是滥用 keep-alive 的结果 - 如果是这样,如何解决?我宁愿不必关闭 keep-alive 来解决问题。

编辑:我已经测试设置以下属性:

        conn.setRequestProperty("Connection", "close"); // supposed to disable keep-alive

发送 Connection: close header 禁用持久的 tcp 连接,所有套接字最终都会被清除。因此,我看到的问题似乎确实与 keep-alive 和套接字没有正确关闭有关,即使在关闭输入流之后也是如此。

EDIT2 - 每次重定向请求时都会创建一个套接字吗?在这个问题很明显的地方,请求在抛出上述异常之前被重定向了 20 次。如果是这种情况,是否有一种方法可以限制 URLConnection 上的重定向次数?

最佳答案

您需要将 conn.disconnect() 移动到您的 finally 部分。因为只有在抛出异常时才会断开连接。

关于java - 爬虫为某些服务器留下大量 ESTABLISHED TCP 套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4773910/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com