Accédant à la portée de la requête haricots dans un environnement multi-thread de l'application web
Scénario:
Nous avons un Printemps réussi application web qui fonctionne à l'intérieur de Websphere. (Spring 3.0.x, 7)
La webapp exploite Websphere travail du manager à l'aide du Printemps WorkManagerTaskExecutor
(configuré avec une taille de pool de threads de 10) pour exécuter de calcul intensif db opérations de lecture. Donc, fondamentalement, une demande arrive à générer, disons, de 10 différents documents. Pour générer les documents uniquement db lectures sont nécessaires pour recueillir/traiter les données. Nous avons donc fondamentalement frayer 10 threads pour traiter le 10 documents et à la fin de rassembler les 10 documents renvoyés à partir de la 10 travailleurs et de les fusionner et écrire de nouveau une grande réponse au client. Ce que nous avons identifié est que tandis que les 10 threads sont de collecte/traitement des données il y a des tas de semblable db appels. Donc, ce que nous avons trouvé est de créer un Aspect autour de la plus-exécuté db méthodes pour mettre en cache la réponse. L'aspect est configuré comme un singleton, et le cache de l'aspect utilise est autocâblés dans l'aspect avec un champ d'application à la demande de la portée, de sorte que chaque demande a son propre cache.
Problème:
Maintenant, le problème avec cette approche est que, si les fils sont en train de faire leur db appels et l'Aspect est dit nous sommes java.lang.IllegalStateException: No thread-bound request found
exception. Je crois comprendre que c'est totalement valide que les threads sont exécutées en dehors du contexte de demande.
Est-il un moyen pour circum-navigation ce problème? Est-il possible d'appliquer l'aspect avec une portée de la requête de la mémoire cache de méthodes invoquées par ces fils?
Vous devez vous connecter pour publier un commentaire.
Je ne pense pas que vous pouvez le faire directement. Même si tu le pouvais, ce serait un peu moche. Cependant, vous pouvez générer un unique identificateur de la demande (ou même utiliser l'id de session, mais attention avec plusieurs onglets), et le passer à chaque thread de traitement. Ensuite, l'aspect peut utiliser l'id de la clé dans le cache. Le cache lui-même sera aussi singleton, mais il y aura
Map<String, X>
, oùString
est l'ID et X est votre résultat mis en cache.Pour rendre les choses plus faciles à gérer, vous pouvez avoir
@Async
méthodes (plutôt qu'à la main de frai threads), et chaque@Async
méthode peut avoir le cache de l'id passé en premier paramètre.(Bien sûr, vos méthodes asynchrones doit retourner
Future<Result>
de sorte que vous pouvez recueillir leurs résultats dans le thread de demande)SimpleAsyncTaskExecutor
au lieu deWorkManagerTaskExecutor
. L'avantage est queSimpleAsyncTaskExecutor
ne sera jamais re-utiliser des threads. C'est seulement la moitié de la solution. L'autre moitié de la solution est d'utiliser unRequestContextFilter
au lieu deRequestContextListener
.RequestContextFilter
a unsetThreadContextInheritable()
méthode qui, en gros, va permettre à l'enfant fils pour hériter le contexte parent.