Как сохранить сокеты Java с низкой задержкой в ​​цикле, используя постоянное соединение Http? - PullRequest
1 голос
/ 06 мая 2019

Я использую программу на Java, которая постоянно загружает некоторые данные из API.Мне нужны эти данные ок.Каждые 1 секунда и низкая задержка важны для моего приложения!Поэтому я сделал что-то вроде этого (псевдокод):

while (true)
   1: download from API
   2: sleep from remainder of 1 sec
end

Среднее время загрузки составляет 40-50 мс.Когда я опускаю время сна (шаг 2), я получаю среднее время загрузки 6-8 мс.

Я пробовал это во многих различных реализациях: HttpUrlConnection, HttpClient (Java11) и Apache HttpClient, но проблема остается.Поэтому я сделал свою собственную реализацию сокетов, но проблема остается.Есть ли способ исправить это?

Я пробовал TCP_NO_DELAY, но безрезультатно.

Моя реализация сокета:

try (Socket socket = new Socket(hostname, 80)) {
    OutputStream writer = socket.getOutputStream();                     
    InputStream input = socket.getInputStream();                       

    for (int i = 0; i < 10; i++) {                   
        //request headers
        String request = "GET " + path + " HTTP/1.1"    + "\r\n" 
                        + "Host: " + hostname           + "\r\n"
                        + "Connection: keep-alive"      + "\r\n"
                        + "\r\n";
        byte[] wb = request.getBytes(StandardCharsets.US_ASCII);        
        writer.write(wb);

        String statusLine       = readInputStatusLine(input);
        LinkedHashMap headers   = readInputHeaders(input);
        String body             = readBody(headers, input);

        //SLEEP FOR A WHILE (THIS CAUSES DELAYS!!??)
        Thread.sleep(1000);                                             
    }
    socket.close();                                                    
}

1 Ответ

0 голосов
/ 06 мая 2019

Еще один Дэйв был прав! Эта проблема вызвана некоторой проблемой на стороне сервера, возможно, кеширующей. Я был в состоянии проверить это и обойти, выполнив 2 последовательных опроса, а затем спал поток. Я просто выбрасываю первый (медленный) опрос и использую только второй (быстрый) опрос. Удалось получить ~ 4-кратное улучшение скорости. Спасибо вам за помощь. Псевдо-код:

while (true)
   1: Do GET and trow away
   2: Do GET and use
   3: sleep for remainder of 1 sec
 end

Настройка кода:

//SLEEP every second time
if (i % 2 == 0 ){
    totalTimeFast += dur;
    System.out.println(i + ": " + statusLine + ", body length = "
        + body.length() + ", dur=" + dur + " ms   FAST");
    Thread.sleep(Math.max(0, 1000-dur));   
} else {
    totalTimeSlow += dur;
    System.out.println(i + ": " + statusLine + ", body length = "
        + body.length() + ", dur=" + dur + " ms   SLOW");
}   

И частичный результат теста N = 100:

90: HTTP/1.1 200 OK, body length = 187136, dur=8 ms   FAST
91: HTTP/1.1 200 OK, body length = 186658, dur=51 ms   SLOW
92: HTTP/1.1 200 OK, body length = 186658, dur=34 ms   FAST
93: HTTP/1.1 200 OK, body length = 186461, dur=51 ms   SLOW
94: HTTP/1.1 200 OK, body length = 186461, dur=7 ms   FAST
95: HTTP/1.1 200 OK, body length = 186374, dur=42 ms   SLOW
96: HTTP/1.1 200 OK, body length = 186374, dur=7 ms   FAST
97: HTTP/1.1 200 OK, body length = 186612, dur=39 ms   SLOW
98: HTTP/1.1 200 OK, body length = 186612, dur=5 ms   FAST
99: HTTP/1.1 200 OK, body length = 186550, dur=36 ms   SLOW
100: HTTP/1.1 200 OK, body length = 186550, dur=13 ms   FAST
Got 100 results with a  totaltimeFast of 1541 ms and totalTimeSlow of 4503 ms
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...