HttpURLConnection#setReadTimeout не влияет при публикации больших сообщений

#java #httpclient

#java #httpclient

Вопрос:

У меня проблема, когда на внешнем HTTP-сервере, на который мне нужно ОТПРАВЛЯТЬ большие сообщения, возникают проблемы с OutOfMemory. У моего HTTP-клиентского кода не истекает время ожидания. Можно воспроизвести это поведение, используя kill -STOP для приостановки процесса HTTP-сервера (для отмены используйте kill -CONT ).

Используя приведенный ниже код, я обнаружил, что если я сохраняю свой запрос небольшим, все сообщение записывается в выходной поток, а время ожидания getResponseCode истекает.

С большим сообщением, подобным приведенному ниже, код связывается при записи в выходной поток. Я предполагаю, что я заполнил буфер сокета. Затем код никогда не истекает.

То, что я ищу, — это способ управления временем ожидания при записи запроса.

Я пробовал что-то подобное, используя Apache HttpClient и получил аналогичный результат. Я попытался запустить приведенный ниже код Java в другом потоке и прервать его сам, но поток продолжает работать.

Мне нужно сохранить потоковое поведение, но я был бы признателен за любые идеи о том, как я мог бы перевести клиентский код в режим ожидания.

Спасибо,

PJ

         URL url = new URL("http://unresponsive/path");
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setUseCaches(false);
        conn.setConnectTimeout(10000);
        conn.setFixedLengthStreamingMode(4 * 1000000);
        conn.setRequestProperty("Content-Length", "4000000");
        conn.setReadTimeout(10000);
        conn.setRequestMethod("POST");
        OutputStream os = conn.getOutputStream();
        for(int i = 0; i < 1000000; i  ) {
            if(i % 1000 == 0) {
                System.out.println("write: "   i);
            }
            os.write("test".getBytes("us-ascii"));
        }
        os.close();
        System.out.println("response-code: "   conn.getResponseCode());
        InputStream is = conn.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line;
        while((line = br.readLine()) != null) {
            System.out.println(line);
        }
        is.close();
  

Ответ №1:

похоже, что вы открываете cnnection и записываете в выходной поток…. Я думаю, что путаница заключается в роли чтения и записи…. Вы не читаете из входного потока, когда ваш код зависает… таким образом, тайм-аут не будет иметь никакого эффекта для спасения связи..

Если есть способ отложить запись, ваш код можно исправить таким образом.

Комментарии:

1. Спасибо jayunit100. Я понимаю, что тайм-аут чтения должен применяться только к чтению ответа, но нет способа установить тайм-аут записи. Я установил время ожидания подключения, но это тоже не помогает.