niejawnie dwa pytania, więc pozwól mi odpowiedzieć zarówno:
1. Jak mogę dostać mój AppEngine instancji do obsługi wielu jednoczesnych żądań?
Naprawdę tylko trzeba zrobić dwie rzeczy:
- Dodaj oświadczenie
<threadsafe>true</threadsafe>
do pliku appengine-web.xml
, który można znaleźć w folderze war\WEB-INF
.
- Upewnij się, że kod wewnątrz wszystkie Twoje zapytanie koparki jest rzeczywiście bezpieczny wątku, to znaczy tylko używać zmiennych lokalnych w swoim
doGet(...)
, doPost(...)
itp metod lub upewnij się zsynchronizować wszystkie dostępu do klasy lub zmiennych globalnych.
to powie usĹ,udze App Engine ram serwera instancja, że kod jest bezpieczny wątku i że jesteś pozwalając mu zadzwonić wszystko swojego zgłoszenia teleskopowe wiele razy w różnych wątkach obsłużyć kilka żądań jednocześnie. Uwaga: AFAIK, Nie jest możliwe ustawienie tego na podstawie serwletu. Więc, twoje serwlety muszą być bezpieczne dla wątków!
W związku z tym opublikowany kod wykonawczy jest już zawarty w kodzie serwera każdej instancji AppEngine i faktycznie wywołuje metodę doGet(...)
z metody uruchamiania oddzielnego wątku tworzonego (lub ponownego użycia) przez AppEngine dla każde żądanie. Zasadniczo doGet()
już jest swój MyTask()
.
Odpowiednia część Dokumentów jest tutaj (choć tak naprawdę nie wiele powiedzieć): https://developers.google.com/appengine/docs/java/config/appconfig#Using_Concurrent_Requests
2. Czy pisał kod przydatna dla (lub jakiegokolwiek innego) cel?
AppEngine w swojej obecnej formie nie pozwala tworzyć własnych wątków i używać ich do akceptowania żądań. To tylko pozwala tworzyć wątki wewnątrz programu obsługi doGet(...)
metodą currentRequestThreadFactory()
wzmiance, ale tylko zrobić przetwarzania równoległego dla tego jednego wniosku i nie do zaakceptowania drugi równolegle (to się dzieje pozadoGet()
).
Nazwa currentRequestThreadFactory()
może być tu trochę myląca. Nie oznacza to, że zwróci onaz RequestThreads
, tj. Wątki, które obsługują żądania. Oznacza to, że zwraca on kod Factory
, który może utworzyć Threads
wewnątrz currentRequest
. Tak więc, niestety, nie można nawet używać zwróconego ThreadFactory poza zakres obecnego wykonania doGet()
, tak jak sugerujesz, tworząc Executor na jego podstawie i utrzymując go w zmiennej klasy.
W przypadku instancji frontend wszelkie wątki tworzone wewnątrz połączenia doGet()
zostaną zakończone natychmiast po zwróceniu metody doGet()
. W przypadku instancji backendowych możesz tworzyć wątki, które nadal działają, ale ponieważ nie masz uprawnień do otwierania gniazd serwera w celu przyjmowania żądań w tych wątkach, nie będą one w stanie samodzielnie zarządzać obsługą żądań.
można znaleźć więcej szczegółów na temat tego, co może i nie można zrobić wewnątrz serwletu interfejsu App Engine tutaj:
The Java Servlet Environment - The Sandbox (konkretnie wątki fragment)
Dla kompletności, zobaczmy w jaki sposób Twój kod może być "legalny":
The Następujące powinny działać, ale nie będzie to miało wpływu na to, że twój kod będzie w stanie obsłużyć wiele żądań równolegle. Będzie to określone wyłącznie przez ustawienie <threadsafe>true</threadsafe>
w twoim appengine-web.xml. Tak więc, technicznie, ten kod jest po prostu bardzo nieefektywny i dzieli zasadniczo liniowy przebieg programu na dwa wątki.Ale tutaj jest tak czy inaczej:
public class MyServlet implements HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
ThreadFactory threadFactory = ThreadManager.currentRequestThreadFactory();
Executor executor = Executors.newCachedThreadPool(threadFactory);
Future<MyResult> result = executor.submit(new MyTask(request)); // Fires off request handling in a separate thread
writeResponse(response, result.get()); // Waits for thread to complete and builds response. After that, doGet() returns
}
}
Ponieważ jesteś już wewnątrz osobnym wątku, który jest specyficzny dla żądanie aktualnie obsługi, powinno się oszczędzić sobie „gwint wewnątrz wątku” i po prostu to zrobić w zamian:
public class MyServlet implements HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
writeResponse(response, new MyTask(request).call()); // Delegate request handling to MyTask object in current thread and write out returned response
}
}
Albo, jeszcze lepiej, po prostu przenieś kod z MyTask.call() do metody doGet(). ;)
bok - Jeśli chodzi o limit 10 jednoczesnych wątków serwletów Państwo wymienić:
Jest to (tymczasowe) projekt-decyzja, która pozwala Google kontrolować obciążenie serwerów łatwiej (konkretnie pamięć użycie serwletów).
Można znaleźć więcej dyskusji na temat tych kwestii tutaj:
Ten wątek został ubzdurałeś do cholery z mnie też, bo jestem zwolennikiem ultra-chudego kodu serwletu, więc moje zwykłe serwlety mogłyby z łatwością obsłużyć setki, jeśli nie tysiące, równoczesnych żądań. Konieczność płacenia za więcej instancji z powodu tego arbitralnego limitu 10 wątków na instancję jest dla mnie trochę irytująca. Ale czytając powyższe linki, wydaje mi się, że są tego świadomi i pracują nad lepszym rozwiązaniem. Więc zobaczmy co Komunikaty Google I/O 2013 przyniesie w maju ... :)
+1 - Bardzo podoba mi się sposób, w jaki myślisz o problemie i sposobie, w jaki próbujesz podejść do rozwiązania. Ale (nie-) na szczęście GAE nie działa w ten sposób, a metoda 'currentRequestThreadFactory()' nie całkiem robi to, czego można się spodziewać na podstawie tego, jak można odczytać jej nazwę. Poniżej zamieściłem odpowiedź, która, mam nadzieję, rozwiąże niejednoznaczność nazwy metody. (It's currentRequest-Thread-Factory, a nie current-RequestThread-Factory);) –
Po prostu z ciekawości: Czy jest coś konkretnego, co próbujesz osiągnąć? Pytam, ponieważ chwilę temu szukałem dokładnie tego samego pytania. Miałem nadzieję, że zaimplementuję coś w rodzaju długich powiadomień push przy użyciu GAE, ale okazało się, że istnieje wiele innych dodatkowych problemów, które staną ci na drodze z czymś takim. GAE jest naprawdę dość ograniczony pod względem możliwości dostosowania sposobu, w jaki planuje i obsługuje zgłoszenia. Niektóre z tych ograniczeń są nieco niejasne ... Ale, oczywiście, to pozwala na to, że jest tak szybki i skalowalny ... –