繁体   English   中英

读取多个URL的Java循环速度变慢

[英]Java loop for reading multiple URL's is slowing down

我已经编写了一些代码来梳理网站上的大约10000个网页,以汇总网站上的用户人口统计资料。 该程序的基础是读取网站源代码的每一行,解析出所需的数据,然后移至下一页。

我遇到一个问题,大约在650页左右,程序从每秒读取3页变为每10-15秒读取1页。 它总是在程序执行的同一时刻发生。 我开始怀疑这可能是程序的内存问题,并开始检查它的各个方面。 最终,我将程序简化为基本内容:

步骤1)创建一个URL对象数组。

步骤2)遍历数组并打开/关闭缓冲的读取器以读取每一行。

步骤3)阅读整个页面,然后移至下一行。

即使这在确切的位置上也变慢了,所以这对我正在解析的数据或将其存储在哪里都不成问题。 这是这种循环的结果。 我想知道我写的内容是否存在引起问题的内存问题? 否则,我唯一的猜测就是我以某种方式拨打电话到网站服务器的速度太快了,这故意使我慢下来。

**显然不是最好的书面代码,因为我是新手,并且要经过一堆草率的编码。 但是它确实可以完美执行我想要的。 问题是它在大约十分钟后减速到爬网的状态,这是行不通的。

以下是相关代码:

数组代码

import java.io.IOException;
import java.net.URL;

public class UrlArrayBuild {

private int page_count; //number of pages 
public URL[] urlArray;  //array of webpage url's

    public UrlArrayBuild(int page) { //object constructor
        page_count = page; //initializes page_count
        urlArray = new URL[page_count]; //initializes page_count
    }

    protected void buildArray() throws IOException { // method assigns strings to   UrlArray object
        int count; //counter for iteration
        for(int i = 0; i < page_count; i++) { //loops through 
            count = i * 60; //sets user number at end of page
            URL website = new URL("http://...." + count);
            urlArray[i] = website; //url address
            //System.out.println(urlArray[i]); //debug
        }
    }

    protected URL returnArrayValue(int index) {  //method returns string value in array of given index
        //System.out.println(urlArray[index]); //debug
        return urlArray[index];
    }

    protected int returnArrayLength() { //method returns length of array
        //System.out.println(urlArray.length); //debug
        return urlArray.length;

    }

}

读码器

import java.net.*;
import java.io.*;

public class DataReader {

public static void main(String[] args) throws IOException {
    UrlArrayBuild PrimaryArray = new UrlArrayBuild(9642); //Creates array object
    PrimaryArray.buildArray();  //Builds array 

    //Create and initialize variables to use in loop
    URL website = null;  
    String inputLine = null;

            //Loops through array and reads source code
    for (int i = 0; i < PrimaryArray.returnArrayLength(); i++) {

        try {
            website = PrimaryArray.returnArrayValue(i);  //acquires url
            BufferedReader inputStream = new BufferedReader(new InputStreamReader(website.openStream()));  //reads url source code
            System.out.println(PrimaryArray.returnArrayValue(i));  //prints out website url.  I use it as a check to monitor progress
            while((inputLine = inputStream.readLine()) != null) {
                if (inputLine.isEmpty()) { //checks for blank lines
                    continue;
                } else {
                    //begin parsing code.  This is currently commented so there is nothing that occurs here
                }
            }
            inputStream.close();
        } finally {
             //extraneous code here currently commented out.  
        }
    }
}

如果网站内容丰富,某些网站可能会因此而造成延迟。 这可能是一个原因。 解析也可能是某些延迟的因素。 因此,我个人建议使用有用的库进行解析,以更好地进行优化。 祝好运!

  1. 多线程应用程序,因此请求可以并发运行。 要么,
  2. 重新架构以使用异步IO / HTTP请求。 Netty或MINA,或者可能只是原始NIO。

这两个相关的解决方案都需要大量工作,但是不幸的是,需要复杂的解决方案来解决您的问题。 基本上,存在异步框架来完全解决此问题。

我认为在遍历数组时,可以使用多线程技术和异步java方法调用来提高性能。

您的代码没有任何明显的错误可以解释这一点。 当然不在您显示给我们的代码中。 您的代码没有保存正在读取的任何内容,因此它不会以这种方式泄漏内存。 而且它不应该泄漏资源...因为如果有任何I / O异常,应用程序将立即终止。

(但是,如果您的代码确实在I / O异常之后尝试继续执行,那么您需要将close()调用移到finally块中,以避免套接字/文件描述符泄漏。)

它很可能是服务器端或(可能是)网络问题:

  • 查看650页标记附近的页面是否有异常。 他们更大吗? 它们是否需要额外的服务器端处理(意味着它们交付速度会更慢)?

  • 查看服务器端负载(在应用程序运行时)及其日志文件。

  • 检查是否已实施某种服务器请求限制; 例如作为一种反DoS措施。

  • 检查是否已实施某种类型的网络流量限制。

  • 还要检查客户端资源使用情况。 我希望CPU使用率保持恒定,或者在650页标记处逐渐减少。 如果CPU使用率增加 ,那将使怀疑重新回到应用程序上。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM