Cela vient de viendoir à l'esprit lorsque vous testez le connecteur Nio Tomcat lors de mes tests de charge. J'utilise en plus de ThreadLocal J'utilise le printemps que je connais à plusieurs endroits qu'il en fait également. p>
Étant donné que le connecteur Nio n'a pas de filetage par connexion, je crains que cela puisse entraîner des bogues très difficiles pour trouver des bogues si un objet threadlocal a été partagé avec un autre fil avant d'être nettoyé. Cependant, je suppose que ce n'est pas un problème car ce n'est pas un avertissement documenté que je pouvais trouver, pas plus que j'ai trouvé d'autres postes d'avertissement à ce sujet. Je suppose que le connecteur Nio n'a aucun effet sur les threads qui servent les demandes réelles. p>
Avant d'aller avec cette hypothèse, j'espérais trouver une preuve concrète. P>
3 Réponses :
Seul quelqu'un familiarisé avec le code Tomcat sera en mesure de vous donner une réponse concrète, mais je vais essayer un en bois :)
Premièrement, vous devez être clair si vous voulez simplement utiliser des connecteurs Nio ou si vous «Réparez aussi des servlets d'asynchronisation. La réponse sera légèrement différente dans chaque cas. P>
La principale chose à prendre conscience est que Java n'a pas une sorte de continuité, de co-routines ou de reformulation de threads. Ce qui signifie qu'une fois que vous avez lancé un morceau de code exécuté sur un thread, seul fort> que em> pièce de code fonctionnera sur le thread jusqu'à ce qu'il complète. P> Donc, si vous avez: Qu'est-ce que pourrait (volonté) est que différents threads seront programmés sur différents Cpus, mais chaque thread exécutera une pièce de code à l'achèvement. P> donc si alors il y a rien à craindre - Donc, un simple connecteur Nio ne devrait pas faire de différence. - Le conteneur appellera la méthode code> Service Code> sur le servlet, le servlet s'exécutera dans un seul fil, puis à la fin, tout est terminé. C'est juste que le conteneur est capable de traiter l'IO de manière plus efficace, car il gère les connexions. P> Si vous utilisez des servlets asyncs, il est un peu différent - dans ce cas, votre servlet peut être appelé Plusieurs fois pour une seule demande (en raison de la manière dont le modèle asynchrone fonctionne), et ces appels pourraient être sur différents threads, vous ne pouvez donc pas stocker quelque chose dans un thread-local entre les invocations de votre servlet. Mais pour un seul appel à votre méthode de service, tout va bien. P> hth. P> p> myObject.Dosomething (); code> alors pour l'heure
DOSOMOD "/ code> est exécuté, il a un accès exclusif à ce fil. Le thread ne va pas basculer sur une autre pièce de code - quel que soit le type de modèle IO que vous utilisez. P>
DOSMATHIAT code> est: p>
dosomiquatoquesse code> sera exécuté un seul thread et le threadlocal sera réglé sur la valeur de droite pour l'exécution complète. p>
Cela signifie-t-il que ThreadLocal est éligible uniquement pour les servlets sans ASYNC code> Code et non approprié pour les servlets qui utilisent ASYNC?
Pour confirmer, c'est toujours un fil qui traite une demande comme vous pouvez vérifier ici de la liste de diffusion Tomcat P>
Pour ajouter à la réponse acceptée de Tim et la question suivante de Pacman, vous devez faire attention lorsque vous utilisez l'asyncresponse ou la fonction similaire avec le connecteur NIO. Je ne suis pas sûr de ce que Tim signifie: "Votre [Async] servlet pourrait être appelé plusieurs fois pour une seule demande" ... mais si une "demande" fait référence à une seule "get" "," post "," post " , ou "Supprimer" puis AFaik qui aboutira à un seul appel à la méthode de ressource correspondante dans votre servlet.
Un problème que vous pourriez rencontrer avec ThreadLocals et les ressources ASYNC est si le thread de traitement de la ressource ASYNC a besoin d'une copie de la ressource ASYNC. la variable threadlocale du fil de boucle d'événement Nio. En d'autres termes, le fil de boucle d'événement NIO accepte une demande puis passe le contrôle de votre ressource ASYNC ... alors cette ressource passe la commande à un fil d'enfant ... alors le fil de boucle d'événement NIO est libre de gérer une autre demande ... Toute variables thénagulables dans le fil de boucle d'événement Nio peut être em> piétiné par la demande suivante. P> Notez qu'il est également possible pour chaque nouvelle demande de faire une nouvelle instance de l'objet stocké dans le threadlocal ... auquel cas chaque nouvelle demande ne marchera pas sur les anciens instances stockées dans la même threadlocale lors de demandes précédentes ... mais vous devez être sûr de ce que vous avez affaire à ... regardons À certains exemples. P> La question initiale fait référence au printemps ainsi un bon exemple est le requérantContExtholder qui a un threadlocal. Disons que le fil de boucle d'événement NIO est nommé "HTTP-NIO-8080-EXEC-1" et il passe le contrôle à une ressource d'asyncresponse qui lance ensuite un nouveau thread (nommé "Pool-2-thread-3") via un exécuteur exécutif . Le nouveau fil a du code qui a besoin de quelque chose à partir des requesttatstributes pour obtenir la réponse à réussir via Asyncresponse.Resume (). Étant donné que le code exécutant dans le fil "piscine-2-thread-3" doit accéder aux demandattributes de "http-nio-8080-exécu-1", vous devez vous assurer que deux choses: p> 1 ) Votre ressource attrape une référence aux demandaTtributes de "http-nio-8080-exécu-1" et la transmet dans "piscine-2-thread-3" p> 2) lorsque "http-nio-8080 -exec-1 "accepte une nouvelle demande qu'il effectuera une nouvelle copie de requestAttributes et définira que dans sa copie de ThreadLocal pour demandeContextholder pour la nouvelle demande (Remarque, le code Spring fonctionne de cette façon, donc c'est sûr). P> < P> Un exemple contraire est la copie threadlocale log4j MDC de la carte. Dans ce cas, chaque nouvelle demande réutilise la même carte ... Donc, il n'est donc pas sûr de transmettre la référence de la carte à partir du fil de boucle d'événement Nio au fil de l'asyncresponse ... Vous devez effectuer une copie de la carte et passer cela. Voir MDCawarethReadpoolExecteur Pour un exemple de comment faire ça. P> Fondamentalement, vous aurez besoin de Vérifiez chaque variable threadlocale que vous devez passer à partir du fil de boucle d'événement NIO dans votre filetage d'asyncresponse ... et voyez s'il est prudent de transmettre une référence à l'objet d'origine, ou si vous devez effectuer une copie de l'objet avant Réglage de la copie dans la variable threadlocale du thread du travailleur. P> BTW, voici un code qui combine les deux exemples ci-dessus: p> de votre ressource d'asyncresponse simplifie simplement Un appel comme celui-ci: p>