2011-10-30 15 views
6

Mój projekt Java AppEngine nie przechowuje żadnych stanu pomiędzy żądaniami wyjątkiem następujących zastosowań Memcache:Lista kontrolna bezpieczny wątku java na AppEngine

  • zobiektywizować używa memcache do buforowania datastore dostaje
  • używam memcache jako sposób na zadania czyszczenia grupowego po wielu żądaniach (np. if (the memcache doesn't think a cleanup task is already running) schedule another cleanup task).

mam żadnych globalnych/statyczne odniesienia do wszelkich obiektów, z wyjątkiem:

  • Obecny uwierzytelniony użytkownik jest utrzymywana w static ThreadLocal<User> obiektu. Oznacza to, że każde żądanie otrzyma swoją własną kopię Użytkownika, prawda?
  • Mam klasę, która obsługuje wszystkie manipulacje danymi, a instancja jest przechowywana jako rodzaj zmiennej globalnej w obiekcie static DataCoordinator.

Czego potrzebuję, aby mój kod był wątkowo bezpieczny? Czy muszę wstawić słowo kluczowe synchronized do każdej deklaracji metody w mojej implementacji DataCoordinator, ponieważ wiele wątków może uzyskać do niej dostęp? Czy to prawda, że ​​obiekt ThreadLocal<User> zawsze tworzy osobny obiekt dla każdego wątku, aby każde żądanie było uwierzytelniane osobno?

Jestem totalną nowicjuszką w myśleniu wątkowym. Co powinienem przeczytać?

Dzięki za pomoc i przepraszam za brak specyfiki.

+0

Czy masz jakieś zajęcia singlton, gdzie można zawsze odwołać się do tej samej instancji poprzez .getInstance()? Jeśli tak, to wiele równoległych żądań wykonywanych w różnych wątkach w tej samej maszynie wirtualnej/instancji może być uzyskiwanie odwołania do tego samego obiektu .... i następnie klasy w ich użyciu lub modyfikacji zmiennych instancji. –

Odpowiedz

7

Pierwszą rzeczą, na którą należy zwrócić uwagę, jest to, że aparat aplikacji może replikować aplikację na wielu serwerach. Oznacza to, że zmienne statyczne będą unikalne tylko na jednym serwerze. Zatem twój DataCoordinator będzie koordynował tylko dostęp do danych na pojedynczym serwerze. Jeśli więc potrzebujesz wspólnych danych do wszystkich serwerów z Twoją aplikacją, powinieneś zawsze używać magazynu danych do tego (lub mechanizmu sesji HTTP GEA w niektórych przypadkach).

Jeśli chodzi o bezpieczeństwo nici DataCoordinator: Należy zsynchronizować tylko metody tego koordynatora, jeśli metody te nie zostały wdrożone w sposób bezpieczny dla wątków. Na przykład nie trzeba synchronizować żadnych metod, które nie mają dostępu do żadnych instancji/statycznych danych, a jedynie pobierają dane z magazynu danych. Jeśli metody mają dostęp do wspólnych danych instancji/statycznych, które są zmienne (jest również zapisywane jednocześnie), w większości przypadków można zsynchronizować na specjalnym monitorze dostęp do danych, zamiast synchronizować na całym koordynatorze.

Odnośnie Twojego ThreadLocal używanego do przechowywania tokena uwierzytelniania: Możesz to zrobić (robię to na przykład w celu uwierzytelnienia użytkownika w gae dla żądań fabrycznych żądania GWT) i tak, każdy wątek będzie miał swoją własną wartość zmiennej, o ile ustawisz to dla tego wątku. Oznacza to, że najlepiej jest upewnić się, że zmienna jest ustawiona dla każdego wątku i zaleca się użycie blokady po ustawieniu, która ostatecznie usunie dane uwierzytelniające po użyciu. Czemu? Najgorszą rzeczą, która mogłaby się zdarzyć, byłoby to, że wątek należący do żądania użytkownika B nadal ma token uwierzytelniający użytkownika A. Dzieje się tak, ponieważ wątki używane w serwerze aplikacji są zwykle łączone między żądaniami, a nie usuwane i ponownie tworzone.

Nie mogę nic powiedzieć o memcache, ponieważ go nie używałem.

Ogólnie należy pamiętać, że wszelkie żądania sieciowe (serwlet/JSP/...) mogą być obsługiwane jednocześnie przez serwer.Tak więc wszelkie zmienne zasoby udostępnione, do których mają dostęp te wątki, powinny być synchronizowane lub implementowane w sposób bezpieczny dla wątków.

Być może http://download.oracle.com/javase/tutorial/essential/concurrency/ jest dobrym punktem wyjścia do przeczytania.

+0

Nie potrzebuję, aby datakoordinator był taki sam dla wszystkich wątków, po prostu potrzebuję go, aby niczego nie zepsuł, gdy dostęp do niego uzyskują dwa konkurencyjne wątki. Dziękuję za odpowiedź - popatrzę na ten samouczek. –

3

Jeśli masz klasy singleton, tylko JEDNA instancja zostanie utworzona/wykorzystana przez Twój kod dla każdej utworzonej VM/Instancji.

odniesienie do niniejszej Singleton mogą być pobrane z:
- dwa kolejne wnioski wykonane jedno po drugim, które są obsługiwane przez tego samego wystąpienia (w zależności od ustawień, jak długo pozostają one wokół, czy zarezerwowanym instancja działa)
- dwa równoległe żądania uruchomione w osobnych wątkach w tej samej instancji, jeśli dla wartości wątków ma wartość true.

Mam napisany i przetestowany kod, aby potwierdzić to dla siebie, a także wdrożyć i przetestować. Jeśli kod w jednym żądaniu używa singletonu do modyfikacji jednej z jego zmiennych składowych, to jest on modyfikowany dla drugiego żądania działającego równolegle.

Wszystko, co logiczne, po ustaleniu czasu życia maszyny wirtualnej i liczbie wątków (tylko 1 lub wiele) jest używanych do obsługi żądań przychodzących.

Ponadto, zmienne systemowe można modyfikować w kodzie w jednym żądaniu i czytać w innym ... Drugi sposób może współdziałać z dwoma równoległymi żądaniami/wątkami.

Zobacz więcej szczegółów na ten temat w moim blogu na wielowątkowości w GAE/J tutaj:
http://devcon5.blogspot.com/2012/09/threadsafe-in-appengine-gaej.html

Powiązane problemy