Параллельные соединения HTTP URL в Java - PullRequest
0 голосов
/ 14 августа 2011

Я занимаюсь разработкой инструмента, который собирает все текстовые файлы из заданной папки. Эти текстовые файлы содержат кучу http URL. Требование заключается в том, что я делаю GET-запрос к этим URL-адресам, регистрирую код ответа и при необходимости распечатываю входной поток. Я должен выполнить это многопоточным способом, и число потоков должно быть настраиваемым. Поэтому я использую TestNG и провайдера данных с параметром parallel = true, чтобы настроить это. Вот что у меня так далеко. Я правильно это делаю?

Редактировать # 2 Другая проблема, которую я обнаружил, заключается в том, что когда я запускаю этот инструмент для URL-адресов 90 Кбайт и для 100 потоков ... Сначала запросы отправляются быстро, но через некоторое время они заметно замедляются. В чем может быть проблема здесь?

Редактировать # 1 Я могу запустить этот инструмент для небольшого количества записей, например нескольких тысяч, но я не могу использовать его для значительно большого количества URL-адресов (250 КБ) и потоков (2500). Я использую ReportNG для создания отчетов. Вот исключения, которые я получаю периодически, когда я запускаю свой инструмент для 250K URL-адресов и 2500 потоков.

java.net.SocketException: Unexpected end of file from server
at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)
at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)
at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at java.net.HttpURLConnection.getResponseCode(Unknown Source)
at com.HTTPConn.doHttpUrlConnectionAction(HTTPConn.java:83)
at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at 

org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:673)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:842)
    at org.testng.internal.TestMethodWithDataProviderMethodWorker.call(TestMethodWithDataProviderMethodWorker.java:73)
    at org.testng.internal.TestMethodWithDataProviderMethodWorker.call(TestMethodWithDataProviderMethodWorker.java:14) 

    [TestNG] Reporter org.uncommons.reportng.HTMLReporter@eee36c failed
org.uncommons.reportng.ReportNGException: Failed generating HTML report.
    at org.uncommons.reportng.HTMLReporter.generateReport(HTMLReporter.java:118)
    at org.testng.TestNG.generateReports(TestNG.java:1053)
    at org.testng.TestNG.run(TestNG.java:1016)
    at com.TestNGRunner.main(TestNGRunner.java:83)
Caused by: java.lang.NullPointerException
    at java.lang.String.compareTo(Unknown Source)
    at org.uncommons.reportng.TestResultComparator.compare(TestResultComparator.java:29)
    at org.uncommons.reportng.TestResultComparator.compare(TestResultComparator.java:25)
    at java.util.Collections.indexedBinarySearch(Unknown Source)
    at java.util.Collections.binarySearch(Unknown Source)
    at org.uncommons.reportng.HTMLReporter.sortByTestClass(HTMLReporter.java:229)
    at org.uncommons.reportng.HTMLReporter.createResults(HTMLReporter.java:180)
    at org.uncommons.reportng.HTMLReporter.generateReport(HTMLReporter.java:110)
    ... 3 more


public class HTTPConn {
    Logger log;
    File folder;
    boolean isStreamRequired;
    @BeforeClass(alwaysRun=true)
    public void setup(){
        log = Logger.getLogger(HTTPConn.class);
        folder = new File("c:\path\to\folder\from\where\I\want\to\read\textfiles");
        isStreamRequired = false;
    }

    @DataProvider(name="getRecords", parallel=true)
    public Object[][] getURLsFromTheFile() throws IOException {
        try {
            File [] listFiles = folder.listFiles();
            int i=0;
            Object[][] result = null;
            ArrayList<String> totalList = new ArrayList<String>();          
            for(int ind=0;ind<listFiles.length;ind++){
                if(listFiles[ind].isFile()){
                    List<String> arrList =FileUtils.readLines(listFiles[ind]); 
                    totalList.addAll(arrList);//add files one by one
                }
            }           
            result=new Object[totalList.size()][];                  
            for(String s:totalList){                        
             result[i]=new Object[]{s};
             i++;
         }              
         return result;
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return null;
    }
 }
    @Test(dataProvider = "getRecords")
    public void doHttpUrlConnectionAction(String desiredUrl){
         try {
              URL url = new URL(desiredUrl);
              HttpURLConnection connection = (HttpURLConnection) url.openConnection();
              connection.setRequestMethod("GET");             
              connection.connect();
              int responseCode = connection.getResponseCode();  
              log.info("\nResponse Code:"+ desiredUrl+"\n"+responseCode+"\n");        
              if(responseCode!=200)
                  Assert.fail("Response Code:"+responseCode);
              else
                  Reporter.log("Response Code:"+responseCode);
              // read the output from the server
              if(isStreamRequired) {
                 //read the input stream and print it to log
                  reader.close();               
            }//isStreamOutputRequired           
              connection.disconnect();           
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }
}

Ответы [ 2 ]

2 голосов
/ 14 августа 2011

Вы пробовали это? Просто напечатайте идентификаторы потока, чтобы дважды проверить, что эти методы действительно работают параллельно. Если это не так, напишите мне небольшой автономный тестовый класс, который показывает проблему.

0 голосов
/ 30 августа 2011

Вот обновление и ответ.

Мне не хватило места в куче, и я не ловил Throwable в своем коде.Как только я добавил, что обнаружил, что у меня заканчивается память.Поэтому я использовал флаг -Xmx512, как показано ниже

java -Xmx512m -jar Tool.jar

Это само по себе не решило проблему.Была проблема с ReportNG, и я постоянно получал исключения.Поэтому я отключил использование ReportNG

Опять же, это не решило проблему. Для URL больше 100 КБ теперь отчет TestNG начал занимать много памяти, поэтому мне пришлось отключить отчет TestNG, изменив флаг setUseDefaultListeners наfalse

После всех этих изменений все начало работать для любого количества записей.Просто у меня на данный момент есть только отчёт log4j, и я могу с этим смириться.

Спасибо всем, что взглянули на это.

...