web-dev-qa-db-fra.com

Spring - server.connection-timeout ne fonctionne pas

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 .

7
series0ne

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.

3

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. 

2
Pankaj Singhal

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.

0
user207421