Я экспериментирую с весной DeferredResult
на Tomcat, и я получаю сумасшедшие результаты. Это то, что я делаю неправильно, или есть какая-то ошибка весной или Tomcat? Мой код достаточно прост.Spring's DeferredResult setResult-взаимодействие с таймаутами
@Controller
public class Test {
private DeferredResult<String> deferred;
static class DoSomethingUseful implements Runnable {
public void run() {
try { Thread.sleep(2000); } catch (InterruptedException e) { }
}
}
@RequestMapping(value="/test/start")
@ResponseBody
public synchronized DeferredResult<String> start() {
deferred = new DeferredResult<>(4000L, "timeout\n");
deferred.onTimeout(new DoSomethingUseful());
return deferred;
}
@RequestMapping(value="/test/stop")
@ResponseBody
public synchronized String stop() {
deferred.setResult("stopped\n");
return "ok\n";
}
}
So. Запрос start
создает DeferredResult
с таймаутом 4 секунды. Запрос stop
установит результат на DeferredResult
. Если вы отправляете stop
до или после истечения срока отсрочки, все работает нормально.
Однако, если вы пришлете stop
в то же время, что и start
раз, все сойдет с ума. Я добавил действие onTimeout
, чтобы это было легко воспроизвести, но это не обязательно для возникновения проблемы. С разъемом APR он просто блокируется. С разъемом NIO он иногда работает, но иногда он неправильно отправляет сообщение «timeout» клиенту stop
и никогда не отвечает клиенту start
.
Чтобы проверить это:
curl http://localhost/test/start & sleep 5; curl http://localhost/test/stop
Я не думаю, что я делаю что-то неправильно. Документация Spring, похоже, говорит, что в любой момент можно позвонить setResult
даже после того, как запрос уже истек, и из любого потока («приложение может произвести результат из потока по своему выбору»).
Используемые версии: Tomcat 7.0.39 на Linux, Spring 3.2.2.
Опасность синхронности методов, когда DeferredResult считается альтернативным способом предоставления асинхронных ответов в соответствии с документацией. http://static.springsource.org/spring/docs/3.2.0.BUILD-SNAPSHOT/api/org/springframework/web/context/request/async/DeferredResult.html Передача синхронного метода предполагает синхронное поведение и может привести к тупиковой ситуации, если не быть осторожным. – dardo
«synchronized's» - это остаток моего исходного кода. Чтобы быть уверенным, я удалил их и перепроверил. Это ничего не изменило. – pdw
Я сообщил об этом выше по течению, и эта ошибка была исправлена весной 3.2.3. – pdw