AsyncHttpClient и тайм-ауты

В AsyncHttpClient JDKFuture.get()

 public V  [More ...] get(long timeout, TimeUnit unit)  {
        V content = null;
        try {
            if (innerFuture != null) {
                content = innerFuture.get(timeout, unit);
            }
        } catch (TimeoutException t) {
            if (!contentProcessed.get() && timeout != -1 && 
              ((System.currentTimeMillis() -   touch.get()) <= responseTimeoutInMs)) {
                return get(timeout, unit);
            }

Почему у нас 2 таймаута?

  1. timeout as param
  2. responseTimeoutInMs

Второй тайм-аут причиняет нам боль, так как звонок не приходит даже после истечения тайм-аута. Он продолжает рекурсивно вызывать get() снова.

Будет ли соединение закрыто после нажатия responseTimeoutInMs? Мы пытаемся установить его ниже тайм-аута.


person Fakrudeen    schedule 29.11.2012    source источник


Ответы (2)


Я предполагаю, что вы имеете в виду метод, который я нашел в сети:

public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
    V content = null;
    try {
        if (innerFuture != null) {
            content = innerFuture.get(timeout, unit);
        }
    } catch (TimeoutException t) {
        if (!contentProcessed.get() && timeout != -1 && ((System.currentTimeMillis() - touch.get()) <= responseTimeoutInMs)) {
            return get(timeout, unit);
        }

        if (exception.get() == null) {
            timedOut.set(true);
            throw new ExecutionException(new TimeoutException(String.format("No response received after %s", responseTimeoutInMs)));
        }
    } catch (CancellationException ce) {
    }

    if (exception.get() != null) {
        throw new ExecutionException(exception.get());
    }
    return content;
}

Вы можете считать этот класс ошибочным в нескольких отношениях. Первая ошибка, которая сразу бросается в глаза, это использование System.currentTimeMillis() вместо System.nanoTime(). System.currentTimeMillis() относится к системным часам компьютера, которые могут быть скорректированы во время выполнения программ и, следовательно, могут прыгать вперед и назад. Код, работающий с тайм-аутами, должен использовать System.nanoTime(), что дает значение, относящееся к выполнению программы, независимое от часов реального мира.

responseTimeoutInMs, по-видимому, подразумевается как тайм-аут соединения, но его использование, даже когда timeout, переданное в качестве значения параметра, истекло, является нарушением контракта Future. Правильным поведением было бы истечение времени ожидания метода get, даже если задача, представленная Future, все еще может выполняться.

Но рекурсивный вызов метода get — двойная ошибка. Рекурсия опасна не только тем, что малые значения времени ожидания могут привести к StackOverflowError; повторная передача одного и того же timeout самому себе означает бесконечную отсрочку тайм-аута, поскольку каждый повторный вызов будет рассматривать это значение как относительно текущего времени.

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

Я не верю, что вы найдете кого-то на stackoverflow, кто может объяснить причину этой реализации, если она вообще существует. Вам нужно будет напрямую обратиться к сторонникам / авторам этого кода.

person Holger    schedule 06.11.2013
comment
Спасибо за объяснение - похоже, это все, что мы можем сделать без помощи авторов. - person Fakrudeen; 07.11.2013

Не используйте провайдера JDK, он сломан и удаляется в AHC 2. Используйте Netty и обновите его до современной версии.

person Stephane Landelle    schedule 08.01.2016
comment
Что сломано в существующем (кроме проблемы выше)? - person matt freake; 08.01.2016
comment
Это всегда была своего рода игрушка, которой никогда не пользовался ни один из коммиттеров. Он не поддерживался, не имел большинства функций и никогда не использовался никем, кроме людей, которые не понимали, что им нужно предоставить такого провайдера, как Netty или Grizzly. AHC 2 будет построен исключительно на базе Netty. - person Stephane Landelle; 08.01.2016