Jaki jest zalecany sposób spawania wątków z servletu w Tomcat [duplicate]

To pytanie ma już odpowiedź tutaj:

Prawdopodobnie powtórzenie! Używam Tomcata jako serwera i chcę wiedzieć, jaki jest najlepszy sposób na wywołanie wątków w servlecie z deterministycznymi wynikami. Uruchamiam kilka długo działających aktualizacji z akcji servlet i chciałbym aby żądanie zostało zakończone i aktualizacje miały miejsce w tle. Zamiast dodawać messaging middleware jak RabbitMQ, myślałem, że mogę wywołać wątek, który może działać w tle i zakończyć w swoim czasie. Czytałem w innych tak wątkach, że serwer kończy wątki zrodzone przez serwer, aby dobrze zarządzać zasobami.

Czy istnieje zalecany sposób wywoływania wątków, zadań w tle podczas korzystania z Tomcat. Używam również Spring MVC dla aplikacji.

Author: BalusC, 2010-09-19

6 answers

Najbezpieczniejszym rozwiązaniem jest użycie szerokiej puli wątków z maksymalną liczbą wątków, dzięki czemu zadania będą w kolejce, gdy zajdzie taka potrzeba. Na ExecutorService jest w tym bardzo pomocny.

Podczas uruchamiania aplikacji lub inicjalizacji servletu Użyj klasy Executors :

executor = Executors.newFixedThreadPool(10); // Max 10 threads.

Następnie podczas obsługi servleta (możesz zignorować wynik dla sprawy, która cię nie interesuje):

Future<ReturnType> result = executor.submit(new CallableTask());

Wreszcie, podczas zamykania aplikacji lub niszczenia servleta:

executor.shutdownNow(); // Returns list of undone tasks, for the case that.
 41
Author: BalusC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-16 22:34:50

Możesz użyć implementacji Commonj WorkManager (JSR 237), takiej jak Foo-CommonJ:

CommonJ - JSR 237 Timer & WorkManager

Foo-CommonJ jest timerem JSR 237 i Implementacja WorkManager. jest przeznaczony do stosowania w pojemnikach, które nie pochodzą z własnych implementacja-głównie zwykły servlet kontenery typu Tomcat . Może być również używany w pełni rozbudowanych aplikacjach Java EE serwery, które nie mają Workmanagera API lub mieć niestandardowe API jak JBoss.

Dlaczego warto korzystać z Workmanagerów?

Powszechnym przypadkiem użycia jest to, że Servlet lub JSP musi agregować dane z wielu źródeł i wyświetlać je w jedna strona. Robienie własnego threadingu a zarządzane środowisko jak J2EE pojemnik jest nieodpowiedni i powinien nigdy nie wykonuj na poziomie aplikacji kod. W tym przypadku interfejs API WorkManager może służyć do pobierania danych w równolegle.

Install/Deploy CommonJ

Rozmieszczenie zasobów JNDI sprzedawca zależny. Realizacja pochodzi z klasą fabryczną, która wdraża javax.naming.spi.ObjectFactory interfejs z sprawia, że łatwo w najpopularniejszych kontenery. Dostępny jest również jako Serwis JBoss. więcej...

Update: dla wyjaśnienia, oto co pisze współbieżne narzędzia dla Java EE Preview (wygląda na to, że jest to następca JSR-236 & JSR-237) o wątkach niezarządzanych:

2.1 zarządzane kontenerami kontra niezarządzane wątki

Serwery aplikacji Java EE wymaga zarządzania zasobami w celu do scentralizowania Administracji i chronić komponenty aplikacji przed zużywanie niepotrzebnych zasobów. To może być osiągnięte poprzez łączenie zasoby i zarządzanie zasobem cykl życia. Używanie współbieżności Java SE narzędzia takie jak java.util.concurrency API, java.lang.Thread oraz java.util.Timer na serwerze komponent aplikacji taki jako servlet lub EJB są problematyczne, ponieważ kontener i serwer nie mają znajomość tych zasobów .

Poprzez rozszerzenie java.util.concurrent API, serwery aplikacji i Java EE kontenery mogą stać się świadomi zasoby, które są wykorzystywane i zapewniają właściwy kontekst wykonania dla operacje asynchroniczne uruchamiane z .

Osiąga się to w dużej mierze poprzez zapewnienie zarządzane wersje dominujących java.util.concurrent.ExecutorService interfejsy.

Więc nic nowego IMO, "stary" problem jest ten sam, niezarządzane wątki są nadal niezarządzane wątki:

  • są one nieznane serwerowi aplikacji i nie mają dostępu do informacji kontekstowych Java EE.
  • [51]} mogą korzystać z zasobów z tyłu serwera aplikacji i bez żadnej zdolności administracyjnej do kontrolowania ich liczby i wykorzystania zasobów, może to wpłynąć na zdolność serwera aplikacji do odzyskiwania zasobów po awarii lub do zamknięcie z gracją.

Referencje

 30
Author: Pascal Thivent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-22 08:21:18

Spring wspiera asynchroniczne zadanie (w Twoim przypadku długie działanie) poprzez spring-scheduling. Zamiast używać Java threads direct proponuję użyć go z Quartz.

Recourses:

 7
Author: Jaydeep Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-19 14:29:26

Ściśle mówiąc, nie wolno wywoływać wątków zgodnie ze specyfikacją Java EE. Rozważyłbym również możliwość ataku typu denial of service (celowego lub innego), Jeśli pojawi się wiele żądań jednocześnie.

Rozwiązanie middleware byłoby zdecydowanie bardziej wytrzymałe i zgodne ze standardami.

 4
Author: dty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-22 08:20:41

Wiem, że to stare pytanie, ale ludzie ciągle je zadają, próbując robić tego typu rzeczy (jawnie spawanie wątków podczas przetwarzania żądania servletu) cały czas... Jest to bardzo błędne podejście - z więcej niż jednego powodu... Samo stwierdzenie, że kontenery Java EE marszczą się na takiej praktyce, nie wystarczy, chociaż ogólnie jest prawdą...

Co najważniejsze, nigdy nie można przewidzieć, ile jednoczesnych żądań servlet otrzyma w danym momencie. Aplikacja internetowa, a servlet, z definicji, ma być zdolny do przetwarzania wielu żądań na danym punkcie końcowym naraz. Jeśli programujesz, żądasz logiki przetwarzania, aby jawnie uruchomić określoną liczbę równoległych wątków, ryzykujesz, że staniesz przed nieuniknioną sytuacją, w której zabraknie dostępnych wątków i udusisz swoją aplikację. Twój wykonawca zadań jest zawsze skonfigurowany do pracy z pulą wątków, która jest ograniczona do skończonej rozsądnej wielkości. Najczęściej nie jest większy niż 10-20 (nie chcesz, aby zbyt wiele wątków wykonywało Twoją logikę - w zależności od charakteru zadania, zasobów, o które konkurują, liczby procesorów na twoim serwerze itp.) Powiedzmy, że Twój handler żądań (np. metoda kontrolera MVC) wywołuje jedną lub więcej metod z adnotacją @Async (w takim przypadku Spring abstrakuje wykonawcę zadania i ułatwia sprawę) lub używa wykonawcy zadania jawnie. W miarę wykonywania kodu zaczyna on pobierać dostępne wątki z puli. To jest w porządku, jeśli jesteś zawsze przetwarzamy jedno żądanie na raz, bez natychmiastowych żądań następczych. (W takim przypadku prawdopodobnie próbujesz użyć złej technologii, aby rozwiązać swój problem.) Jeśli jednak jest to aplikacja webowa, która jest narażona na arbitralne (lub nawet znane) klienty, które mogą uderzać w punkt końcowy żądaniami, szybko wyczerpiesz pulę wątków, a żądania zaczną się gromadzić, czekając na dostępność wątków. Tylko z tego powodu powinieneś zdać sobie sprawę, że możesz być na złej drodze - jeśli rozważasz taki projekt.

Lepszym rozwiązaniem może być stage danych, które mają być przetwarzane asynchronicznie (może to być Kolejka lub inny rodzaj tymczasowego/tymczasowego magazynu danych) i zwrócenie odpowiedzi. Korzystaj z zewnętrznej, niezależnej aplikacji lub nawet wielu jej instancji (wdrożonych poza kontenerem sieciowym), sprawdzając punkty końcowe i przetwarzając dane w tle, prawdopodobnie przy użyciu skończonej liczby równoległych wątków. Nie tylko takie rozwiązanie daje Ci przewagę przetwarzania asynchronicznego/współbieżnego, ale również skaluje, ponieważ będziesz mógł uruchomić tyle instancji takiego Pollera, ile potrzebujesz, i mogą być rozproszone, wskazując na punkt końcowy. HTH

 4
Author: cvnew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-04 07:01:27

Od wiosny 3 Można używać adnotacji @asynchronicznych:

@Service
public class smg {
  ...
  @Async
  public getCounter() {...}
}

Z <context:component-scan base-package="ch/test/mytest"> i <task:annotation-driven/> w pliku kontekstowym

Proszę zapoznać się z tym samouczkiem: http://spring.io/blog/2010/01/05/task-scheduling-simplifications-in-spring-3-0/

Działa świetnie dla mnie na Tomcat7 i nie musisz zarządzać pulą wątków.

 2
Author: Nereis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-18 07:35:36