2011-12-14 2 views
2

Я хочу написать простой инструмент сравнения в java, который будет разворачивать потоки x и набирать url y раз в общей сложности.написать простой инструмент для сравнения в java

Фактическая часть задачи сделает веб-запрос на URL-адрес и отправит файл XML.

Итак, что я хочу сделать, открутите 50 потоков и продолжайте нажимать на URL, пока я не сделаю 10K запросов.

Может кто-нибудь объяснить, как это сделать, я считаю, что использование службы-исполнителя - это путь.

Некоторые вещи, чтобы рассмотреть следующие вопросы:

  1. После того, как поток завершается, я предполагаю, что это будет сразу же запустить другую задачу правильно?
  2. Мне нужен поток для возврата, поскольку я должен отслеживать успех/неудачи, где это должно быть сохранено (оно должно быть потокобезопасным).
+0

что у вас до сих пор? – jtahlborn

+0

Вы уверены, что не имеете в виду «симулятор нагрузки»? Бенчмаркинг обычно включает в себя некоторую проблему скорости, где это звучит как «ударил мой 10k раз и посмотрел, сколько запросов терпит неудачу». Я спрашиваю, потому что, если вам нужен тест, а не стресс-тест, результаты будут разными. – jefflunt

+0

@jtahlborn У меня есть реальная задача запустить i.e post xml-файл на мой url. – codecompleting

ответ

3

Да, ExecutorService является идеальным выбором для этой задачи:

ExecutorService exec = Executors.newFixedThreadPool(50); 

Время начала измерения и просто представить 10K задачи ему:

for(int i = 0; i < 10000; ++i) { 
    exec(new SubmitToUrlTask()); 
} 

Рассмотрим, используя тот же экземпляр (без гражданства или потокобезопасным) SubmitToUrlTask, а не создавать новые на каждой итерации.

В конце концов, вы должны ждать исполнителя закончить:

exec.shutdown(); 
if(!exec.awaitTermination(1, TimeUnit.MINUTE)) { 
    throw new IllegalStateException("Waiting for too long, captain!"); 
} 

остановки измерения времени в настоящее время. awaitTermination() блокировки до все задачи завершены, но не дольше, чем заданное время (1 мин. В примере).

Как только поток закончен, я предполагаю, что он немедленно запустит другую задачу правильно?

Да, ExecutorService - это куча нитей и очередь задач. Если нить не имеет ничего общего, она берет первую задачу из очереди.

Мне нужен поток для возврата, поскольку я должен отслеживать успех/неудачи, где это должно быть сохранено (оно должно быть потокобезопасным).

Callable<Boolean> и Future<Boolean> для отслеживания результатов. Также, если вы используете только один экземпляр SubmitToUrlTask, он может иметь две переменные типа AtomicInteger, отслеживая как успехи, так и неудачи. Это намного проще, если вам не нужно отслеживать отдельные результаты.

Если вы считаете, что используете JMeter, который имеет все эти функциональные возможности + намного больше из коробки? Существует также консольная утилита ab.

+0

, но мне нужно будущее, чтобы получить результат обратно? – codecompleting

+0

@codecompleting: Да, я действительно добавил это к моему ответу, пока вы разместили свой вопрос. См. Мое обновление. –

+0

Да, я знаю jmeter, я хочу также изучить это, но также написать свой собственный инструмент. – codecompleting

1

Вот аннотированный исходный код, который описывает стратегию вы можете использовать:

import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.atomic.AtomicInteger; 

public class LoadGen { 
    /** 
    * Hits the given url for nRequests times on nUsers threads. 
    * 
    * @return LoadGen.Result object with status of the test 
    */ 
    public static Result generateLoad(final String url, 
     int nUsers, int nRequests) throws InterruptedException { 
     // A thread pool with one thread per simulated user 
     ExecutorService threadPool = Executors.newFixedThreadPool(nUsers); 

     // A latch awaited on by the user threads before the test is started 
     final CountDownLatch startSignal = new CountDownLatch(1); 

     // A latch awaited on by the main thread for all user threads 
     // to complete the test 
     final CountDownLatch doneSignal = new CountDownLatch(nUsers); 

     // The Result object for this test run 
     final Result result = new Result(nRequests); 

     // Submit one Runnable per simulated user 
     for (int i = 0; i < nUsers; i++) { 
      threadPool.submit(new Runnable() { 
       public void run() { 
        try { 
         // the Runnable awaits for the test to start 
         startSignal.await(); 

         runSimulatedUser(url, result); 

         // indicate that this thread has completed 
         doneSignal.countDown(); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 
      }); 
     } 

     // Start all simulated user threads 
     startSignal.countDown(); 

     // Wait for all simulated user threads to complete the test 
     doneSignal.await(); 

     // Dispose all threads 
     threadPool.shutdownNow(); 
     return result; 
    } 

    private static void runSimulatedUser(String url, Result result) { 
     // run repeatedly .. 
     while (true) { 
      try { 
       // hitting the URL, marking success and failure 
       // until nRequests requests are made in total 
       makeRequest(url); 
       if (! result.success()) { 
        break; 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
       if (! result.failure()) { 
        break; 
       } 
      } 
     } 
    } 

    private static void makeRequest(String url) { 
     // TODO: post the XML document to the URL etc 
     System.out.println("Making request"); 
    } 

    public static class Result { 
     private final AtomicInteger nSuccess = new AtomicInteger(); 
     private final AtomicInteger nFailure = new AtomicInteger(); 
     private final AtomicInteger nTotal; 

     public Result(int nTotal) { 
      this.nTotal = new AtomicInteger(nTotal); 
     } 

     boolean success() { 
      nSuccess.incrementAndGet(); 
      return nTotal.decrementAndGet() > 1; 
     } 

     boolean failure() { 
      nFailure.incrementAndGet(); 
      return nTotal.decrementAndGet() > 1; 
     } 

     int getSuccessCount() { 
      return nSuccess.get(); 
     } 

     int getFailureCount() { 
      return nFailure.get(); 
     } 
    } 

    public static void main(String[] args) throws Exception { 
     // generate 10 requests on 2 threads 
     LoadGen.generateLoad("http://myurl.com", 2, 10); 
    } 
}