【发布时间】:2016-12-11 23:22:59
【问题描述】:
我有一个 java 代码来废弃页面的内容。一次我执行 2500 个线程,每个线程有 100 个要废弃的 url。所有线程都成功执行,但很少有线程永远挂起而不抛出任何异常。使用 ubuntu 作为生产服务器。 代码卡在下面一行:
InputStream in = urlConnection.getInputStream();
我在做连接和读取超时,这是有效的。即使线程很少,读取超时也不起作用,它会永远挂起。 我已经尝试过很多工作,但都失败了。
我什至使用 thread.stop()杀死了挂起的线程(不推荐的方法)但是挂起的线程 tcp 连接在 linux 服务器上仍然存在。
java 7325 root 2675u IPv4 284078467 0t0 TCP scrapper-new-instance-2.c.quantum-tracker-93805.internal:37068->104.131.210.5:22225 (ESTABLISHED)
java 7325 root 2688u IPv4 284077787 0t0 TCP scrapper-new-instance-2.c.quantum-tracker-93805.internal:38132->104.131.210.5:22225 (ESTABLISHED)
java 7325 root 2723u IPv4 284057771 0t0 TCP scrapper-new-instance-2.c.quantum-tracker-93805.internal:43661->104.131.210.5:22225 (ESTABLISHED)
任何人有想法,我可以如何调试和修复这个问题?
下面是代码片段:
int counter = 0;
int maxAttempts = (config.getProperty("maxAttempts") != null ? Integer.parseInt(config
.getProperty("maxAttempts")) : 100);
Proxy proxy = null;
while (counter < maxAttempts) {
try {
Type proxyType = Proxy.Type.HTTP;
String proxyIP = "";
int proxyPort;
int proxyIndex = getRandomNumber(1, httpProxies.size());
if(httpProxies.get(proxyIndex).split(":").length == 4){
proxyIP = httpProxies.get(proxyIndex).split(":")[0];
proxyPort = Integer.parseInt(httpProxies.get(proxyIndex).split(":")[1]);
if (httpProxies.get(proxyIndex).split(":").length == 3) {
if (httpProxies.get(proxyIndex).split(":")[2].toLowerCase().contains("socks"))
proxyType = Proxy.Type.SOCKS;
}
}else{
counter = counter - 1;
throw new Exception("Escapeing for IP --- "+httpProxies.get(proxyIndex));
}
URL url = new URL(urlSring);
InetSocketAddress inetSocketAddress = new InetSocketAddress(proxyIP, proxyPort);
proxy = new Proxy(proxyType,inetSocketAddress);
int userAgentIndex = getRandomNumber(1, userAgents.size());
logger.info("Attempt = " + counter + " using proxy " + httpProxies.get(proxyIndex) + " (" + proxyType.name()
+ ") for url " + urlSring);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(proxy);
if (config.getProperty("connectionTimeoutInMilliSecs") != null)
urlConnection
.setConnectTimeout(Integer.parseInt(config.getProperty("connectionTimeoutInMilliSecs")));
else
urlConnection.setConnectTimeout(CONNECTION_TIMEOUT_VALUE);
if (config.getProperty("readTimeoutInMilliSecs") != null)
urlConnection.setReadTimeout(Integer.parseInt(config.getProperty("readTimeoutInMilliSecs")));
else
urlConnection.setReadTimeout(READ_TIMEOUT_VALUE);
System.setProperty("http.agent", "");
urlConnection.setRequestProperty("User-Agent", "");
urlConnection.setRequestProperty("User-Agent", userAgents.get(userAgentIndex));
urlConnection.addRequestProperty("Accept-Encoding", "gzip, deflate, br"); // to avoid server returned http response code 403
urlConnection.setInstanceFollowRedirects(true);
//Few Thread hang here for ever
InputStream in = urlConnection.getInputStream();
if(null != urlConnection.getContentEncoding() && urlConnection.getContentEncoding().equals("gzip")){
in = new GZIPInputStream(in);
}
String output = IOUtils.toString(in, Charset.forName("UTF-8").name());
logger.info("Proxy Address:-"+proxy.address()+ " HTTP Response Code : " + urlConnection.getResponseCode() + " HTTP Response Message : "
+ urlConnection.getResponseMessage() + " for url ---" + urlSring);
logger.info("Success scraping for url --- "+urlSring+ " --- using proxy --- "+httpProxies.get(proxyIndex));
// Close Input Stream
if(in != null){
in.close();
}
// Close url connection and release underlying socket if exists.
if(urlConnection != null){
urlConnection.disconnect();
}
url = null;
urlConnection = null;
return output;
} catch (Exception e) {
logger.info(e);
counter++;
/*
* logger.info("Exception : " + e.getMessage() + " while using proxy " + proxy.address() +
* ".Trying next proxy.");
*/
if (config.getProperty("shouldSleepBetweenRequests") != null
&& config.getProperty("shouldSleepBetweenRequests").equalsIgnoreCase("true")) {
Random r = new Random();
int low = config.getProperty("minSleepTime") != null ? Integer.parseInt(config
.getProperty("minSleepTime")) : 0;
int high = config.getProperty("maxSleepTime") != null ? Integer.parseInt(config
.getProperty("maxSleepTime")) : 5;
int timeToSleep = r.nextInt(high - low) + low;
logger.info("Sleeping for " + timeToSleep + " seconds ... ");
try {
Thread.sleep(timeToSleep * 1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
}
if (counter >= maxAttempts)
logger.info("Stoping after " + maxAttempts + " attempts ...for url "+ urlSring);
return "";
请分享您的想法,并告诉我如何解决此问题。 我不想杀死挂起的线程,而是如果可能的话,我想为这种情况实现一些超时。
【问题讨论】:
标签: java linux multithreading http tcp