Dans mon fichier application.properties
j'ai ...
server.port=8086
server.connection-timeout=15000
Je sais que le fichier est chargé correctement car le serveur s'exécute sur le port 8086.
Dans l'application, j'ai une RestController
@RestController
class TestController {
@GetMapping()
fun getValues(): ResponseEntity<*> {
return someLongRunningProcessPossiblyHanging()
}
}
Lorsque j'appelle le noeud final, la requête n'expire jamais, elle reste suspendue indéfiniment.
Est-ce que je manque quelque chose?
NOTE: On m'a également informé que Tomcat utilisait ce champ en quelques minutes, et non en millisecondes (choix plutôt inhabituel à l'OMI). J'ai essayé de régler ceci sur server.connection-timeout=1
représentant 1 minute, mais cela ne fonctionnait pas non plus.
NOTE: Je ne veux pas que une autre _ requête HTTP entraîne l'expiration de la requête précédente, je souhaite que chaque requête HTTP expire de son propre chef, si trop de temps s'écoulait pour la traiter .
connection-timeout
ne s'applique pas aux requêtes de longue durée. Cela s'applique à la connexion initiale, lorsque le serveur attend que le client dise quelque chose.
Les documents Tomcat (pas Spring Boot) le définissent comme suit: nombre de millisecondes que ce connecteur attendra, après l'acceptation d'une connexion, que la ligne d'URI de demande soit présentée [...]
Pour tester le paramètre server.connection-timeout=4000
, je me connecte avec netcat
et je n’envoie aucune requête/en-tête HTTP. Je reçois:
$ time nc -vv localhost 1234
Connection to localhost 1234 port [tcp/*] succeeded!
real 0m4.015s
user 0m0.000s
sys 0m0.000s
Alternatives
1) Async
De brightinventions.pl - Printemps des pools de threads MVC de printemps :
Dans Spring MVC, il est impossible de configurer un délai d'expiration à moins d'utiliser une méthode asynchrone. Avec la méthode async, on peut utiliser spring.mvc.async.request-timeout = pour définir le délai (en millisecondes) avant l’expiration du délai de traitement des demandes asynchrones.
J'ai mis spring.mvc.async.request-timeout=4000
et j'ai un timeout dans le navigateur avec ceci:
@GetMapping("/test-async")
public Callable<String> getFoobar() {
return () -> {
Thread.sleep(12000); //this will cause a timeout
return "foobar";
};
}
Voir API Spring Boot REST - Délai d'expiration de la demande?
2) Filtre de servlet
Une autre solution consisterait à utiliser un filtre de servlet brightinventions.pl - Expiration des demandes dans Spring MVC (Kotlin):
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
val completed = AtomicBoolean(false)
val requestHandlingThread = Thread.currentThread()
val timeout = timeoutsPool.schedule({
if (completed.compareAndSet(false, true)) {
requestHandlingThread.interrupt()
}
}, 5, TimeUnit.SECONDS)
try {
filterChain.doFilter(request, response)
timeout.cancel(false)
} finally {
completed.set(true)
}
}
3) Vanne de détection de fil coincé Tomcat?
Tomcat a une vanne de détection de fil bloquée mais je ne sais pas si cela peut être configuré par programme à l'aide de Spring Boot.
Depuis le fonctionnaire docs :
server.connection-timeout = # Délai pendant lequel les connecteurs attendent une autre requête HTTP avant de fermer la connexion. Lorsqu'il n'est pas défini, la valeur par défaut spécifique au conteneur du connecteur est utilisée. Utilisez une valeur de -1 pour indiquer aucun délai (c'est-à-dire un délai infini).
Un autre ref mentionne également les mêmes. Il devrait fonctionner pour vous.
Lorsque j'appelle le noeud final, la requête n'expire jamais, elle reste suspendue indéfiniment.
server.connection-timeout
n'est pas un délai d'attente de demande. C'est un délai d'attente pour les connexions inactives, c'est-à-dire celles qui ont déjà eu une paire requête/réponse et sur lesquelles le serveur attend maintenant une seconde requête. Il s'agit essentiellement d'un délai d'attente de lecture côté serveur.