Vor kurzem in meinem Projekt musste ich einige Aufgaben asynchron durchführen. Da wir eine Webapp mit Spring in einem Tomcat ausführen, war der ThreadPoolTaskExecutor von Spring eine Lösung.
Allerdings hat der Architekt einige Einwände erhoben und erklärt, dass es schrecklich / verboten / absolut böse ist, einen Thread zu spawnen / einen Thread-Pool in einer Webapp zu haben.
Als ich ein wenig im Netz und auf StackOverflow suchte, erkannte ich, dass es eine schlechte Übung ist, einen eigenen Thread-Pool innerhalb eines Java EE Containers zu haben. Der Grund dafür war, dass der Container, der über einen eigenen Threadpool verfügt, diesen nicht kennt und Ressourcen nicht ordnungsgemäß verwalten kann. Dies ist besonders wichtig, wenn Sie einige heiße Bereitstellungen Ihrer Webanwendung durchführen müssen.
Nun ist unser Anwendungsfall eine Spring-Webanwendung, die in Tomcat ausgeführt wird. Erstens, können wir den Spring Container als einen leichten Java EE Container betrachten? In diesem Fall verwaltet Spring den Threadpool-Lebenszyklus und nicht die Anwendung selbst, oder?
Zweitens gilt das Hot-Deployment-Argument auch für diese Konfiguration?
Und ja, ich weiß, dass es möglich ist, einen Arbeitspool direkt in Tomcat zu deklarieren und ihn über JNDI in Spring zu injizieren. Aber es ist ein bisschen mühsam im Vergleich zu der direkten ThreadPoolTaskExecutor-Funktion von Spring
Meine letzte Frage ist also: ist der Einspruch des Architekten in meinem Fall relevant?
Danke für Ihre Anregungen und Gedanken zu diesem Thema.
Es gibt verschiedene Ebenen des Bösen, und nicht alle zählen in jeder Situation als böse.
Das Erstellen von Threads nach Bedarf anstatt eines Pools wird in der Regel als schlecht angesehen, aber das gilt nicht nur für Java EE und gilt für fast jede Art von Serveranwendung.
In Java EE ist das Erstellen eigener Threads insbesondere im EJB-Container nicht erlaubt. Dies liegt unter anderem daran, dass Java EE-Container möglicherweise kontextbezogene Daten im lokalen Threadspeicher unsichtbar speichern, was verloren geht, wenn Code in einem eigenen Thread ausgeführt wird.
Der Web-Container hat jedoch keine solchen Einschränkungen und gemäß der Spezifikation ist es mehr oder weniger legal, Thread-Pools zu haben. Dies ist zum Beispiel der Grund, warum Leute Quartz von einem Webmodul in einer EAR starteten, selbst wenn nur EJB-Module verwendet wurden oder warum Code innerhalb des Webmoduls Callback-Listener in nicht verwalteten JMS-Warteschlangen registrieren konnte, EJBs jedoch nicht Mach das.
In der Praxis funktioniert das Erstellen von Threads (über Pools) jedoch fast immer, solange Sie bedenken, dass wenn Sie z. EJB Sie müssen Instanzen von JNDI in Code erwerben, der in diesen Threads ausgeführt wird, und keine Referenzen von EJBs an diese nicht verwalteten Threads weiterleiten. Natürlich müssen Sie darauf achten, Ihren Pool herunterzufahren, aber fast jede Art von Start-Listener in Java EE verfügt über einen entsprechenden Shutdown-Listener, wo Sie dies tun können.
Java EE hat einige offizielle Möglichkeiten, die die Notwendigkeit zum Erstellen eigener Pools verringern:
AsyncContext#start()
(das von allgemeinem Nutzen ist, siehe Was ist der Zweck von AsyncContext.start (...) in Servlet 3.0? ) Einige Algorithmen erfordern jedoch separate Thread-Pools, um Dead-Lock-Möglichkeiten zu vermeiden. Da keine der Java EE-Lösungen Ihnen die absolute Sicherheit gibt, dass die Arbeit von verschiedenen Thread-Pools erledigt wird, gibt es manchmal einfach keine andere plausible Möglichkeit, als einen eigenen Pool zu erstellen.
In der letzten Situation ist es also böser, den Code für Dead-Locks zu öffnen, als einen eigenen Thread-Pool zu erstellen.
Imho mit selbstverwalteten TaskExecutoren in einer Java EE-Anwendung ist keine schlechte Übung, wenn sie ordnungsgemäß isoliert ist. Die Trennung von asynchronen Aufgaben in eine isolierte Instanz führt zu einer neuen Komplexitätsebene, einer neuen Abhängigkeit und reduziert die Leistung.
Das Architekten-Argument, das nicht verwaltet wird, ist natürlich nullbar, da der Container viele Instanzen (zB statische Referenzen) nicht kennt / besitzt und Sie den Executor selbst innerhalb einer @Configuration-Klasse oder innerhalb der Spring-Konfigurationsdatei konfigurieren können Dadurch wird zumindest der Executor selbst vom Container verwaltet.
Darüber hinaus bietet Spring selbst mehrere Methoden zum Ausführen von geplanten Methoden, z. B. mithilfe der @ Scheduled-Annotation (http://static.springsource.org/spring/docs/3.0.x/reference/scheduling.html)
Eine Hot Deployment-Abhängigkeit hängt davon ab, wie Ihre Arbeitswarteschlange konfiguriert ist und wie Ihre asynchrone Task sie verarbeitet.
Tags und Links spring tomcat threadpool