Я не являюсь экспертом по многопоточности, но вижу некоторые проблемы с производительностью в моем текущем коде, который использует ExecutorService
.
Я работаю над проектом, в котором мне нужно сделать HTTP-вызов URL-адреса на мой сервер, и если ответ занимает слишком много времени, то прервите вызов. В настоящее время он возвращает простую строку JSON обратно.
Текущее требование у меня есть для 10 ms
. В пределах 10 ms
он должен иметь возможность получить данные с сервера. Я предполагаю, что это возможно, поскольку это просто HTTP-вызов на сервер в том же центре обработки данных.
Моя клиентская программа и фактические серверы находятся в одном центре обработки данных, и задержка пинга между ними составляет 0.5 ms
, поэтому это наверняка выполнимо.
Я использую RestTemplate
для этого, чтобы сделать вызов URL.
Ниже приведен мой код, который я написал для себя, который использует ExecutorService
и Callables
-
public class URLTest {
private ExecutorService executor = Executors.newFixedThreadPool(10);
public String getData() {
Future<String> future = executor.submit(new Task());
String response = null;
try {
System.out.println("Started..");
response = future.get(100, TimeUnit.MILLISECONDS);
System.out.println("Finished!");
} catch (TimeoutException e) {
System.out.println("Terminated!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return response;
}
}
Ниже мой класс Task, который реализует интерфейс Callable
-
class Task implements Callable<String> {
private RestTemplate restTemplate = new RestTemplate();
public String call() throws Exception {
// TimerTest timer = TimerTest.getInstance(); // line 3
String response = restTemplate.getForObject(url, String.class);
// timer.getDuration(); // line 4
return response;
}
}
А ниже мой код в другом классе DemoTest
, который вызывает метод getData
в классе URLTest
500 times
и измеряет его 95-й процентиль от начала до конца -
public class DemoTest {
public static void main(String[] args) {
URLTest bc = new URLTest();
// little bit warmup
for (int i = 0; i <= 500; i++) {
bc.getData();
}
for (int i = 0; i <= 500; i++) {
TimerTest timer = TimerTest.getInstance(); // line 1
bc.getData();
timer.getDuration(); // line 2
}
// this method prints out the 95th percentile
logPercentileInfo();
}
}
С приведенным выше кодом я всегда вижу 95-й процентиль как 14-15 ms
(что плохо для моего варианта использования, поскольку это сквозной поток, и это то, что мне нужно измерить).
удивляюсь почему? ExectuorFramework
добавляет сюда всю задержку? Может быть каждая задача отправлена, и поток отправки ожидает (через future.get), пока задача не будет завершена.
Моя главная цель - максимально уменьшить задержку здесь. Мой вариант использования прост: сделать вызов URL-адреса на один из моих серверов с включенной функцией TIMEOUT, что означает, что если серверу требуется много времени для ответа, то тайм-аут весь звонок. Клиент будет вызывать наш код из приложения, которое также может быть многопоточным.
Есть ли что-то, что мне не хватает, или какие-то другие варианты ExecutorService
, которые мне нужно использовать? Как я могу улучшить свою работу здесь? Любые предложения будут очень полезны ..
Будем очень признательны за любой пример. Я читал о ExecutorCompletionService
, не уверен, следует ли мне использовать это или что-то еще..
14-15 ms
? - person arsenal   schedule 20.01.2014