Tworzę usługi sieciowe, które miałyby 2000 równoczesnych użytkowników. Usługi są oferowane za darmo i dlatego oczekuje się, że uzyskają dużą bazę użytkowników. W przyszłości może być konieczne skalowanie do 50 000 użytkowników.
Jest już kilka innych pytań dotyczących tego problemu, takich jak - /programming/2567254/building-highly-scalable-web-services
Jednak moje wymagania różnią się od powyższego pytania.
Na przykład - Moja aplikacja nie ma interfejsu użytkownika, więc obrazy, CSS, javascript nie stanowią problemu. Jest w Javie, więc sugestie takie jak użycie HipHop do tłumaczenia PHP na kod natywny są bezużyteczne.
Dlatego postanowiłem zadać pytanie osobno.
To jest konfiguracja mojego projektu -
- Usługi sieciowe oparte na spoczynku przy użyciu Apache CXF
- Hibernacja 3.0 (z odpowiednimi optymalizacjami, takimi jak leniwe ładowanie i niestandardowy HQL do dostrojenia)
- Tomcat 6.0
- MySql 5.5
Jakie są najlepsze praktyki, aby skalować aplikację Java?
źródło
Odpowiedzi:
W przeszłości zajmowałem się tym problemem, ale nadal uważam, że mam wiele do nauczenia się w terenie. Uważam, że jest to jedno z najciekawszych obszarów rozwoju oprogramowania, oto kilka przemyśleń na ten temat:
MySQL jest wystarczająco uczciwą bazą danych, chyba że pracujesz z ogromną ilością danych, aw tym przypadku możesz rozważyć NoSQL baza danych, ale należy dokładnie sprawdzić, która baza danych NoSQL jest najlepsza dla Twoich potrzeb.
Należy wdrożyć buforowanie w systemie - spróbować buforować jak najwięcej danych tylko do odczytu lub zdefiniować niektóre strategie buforowania - na przykład mieliśmy scenariusz, w którym użytkownik widział „stare dane” jako tak długo, jak ostatnia aktualizacja miała miejsce w ciągu ostatniej godziny.
Rozważyłbym JBoss Cache, a może Infinispan (który bardziej przypomina rozproszoną strukturę danych) lub inne popularne ramy buforowania do tego.
Ponadto, jak wspomniałeś tomcat, zakładam, że pracujesz w jakimś module odpowiadającym na żądania. Spróbuj rozważyć użycie pamięci podręcznej, która istnieje w zakresie danego żądania, może to być nawet prosta HashMap powiązana z lokalnym magazynem wątków .
Mój pomysł tutaj przypomina pamięć podręczną pierwszego poziomu w Hibernacji .
Należy pamiętać, że pliki, transakcje i inne zasoby są drogie pod względem utrzymywania ich w stanie otwartym. Upewnij się, że zamykasz pliki i transakcje tak szybko, jak to możliwe, w przeciwnym razie pojawią się błędy, które będą odtwarzane w dużych konfiguracjach
Ponadto musisz zrozumieć, co 2000 równoczesnych użytkowników - czy to oznacza, że 2000 użytkowników uzyskuje dostęp do twojego serwera jednocześnie, czy też korzystają z twojego systemu? Rozróżnij przypadki, w których 2000 użytkowników próbuje otworzyć gniazdo na serwerze, a przypadki, w których tylko 500 jest, a 1500 szuka obecnie rezultatów wypełniania danych wejściowych po stronie klienta.
Powinieneś rozważyć użycie klastrowania - będziesz musiał poradzić sobie z takimi problemami, jak równoważenie obciążenia , sesja lepka (co oznacza, że moduł równoważenia obciążenia przekieruje żądanie do tego samego serwera dla tej samej sesji) i więcej.
Jeśli potrzebujesz kodu synchronizacji - ostrożnie wybierz strategię synchronizacji. Widziałem niektóre systemy, w których zastosowano prostą blokadę, ale ReaderWriterLockmógł poprawić, ponieważ większość dostępu była tylko do odczytu.
Rozważ buforowanie i sprawdzanie poprawności po stronie klienta, jeśli to możliwe, spróbuj zapisywać połączenia do serwera i wysyłać tylko różnice danych, na wypadek gdyby większość odpowiedzi na żądanie z tym samym parametrem się nie zmieniła.
Na przykład w projekcie open source oVirt prosimy o uzyskanie statystyk dotyczących danej maszyny wirtualnej. niektóre dane maszyny wirtualnej rzadko się zmieniają, więc wysyłamy tylko MD5, jeśli dane się zmienią, wartość MD5 również ulega zmianie, wykonujemy żądanie uzyskania pełnych danych, a nie tylko MD5.
Wspomniałem wcześniej o hibernacji - chciałbym ponownie rozważyć użycie go - jeśli chcesz wykonać wiele zapisów i mniej odczytów, Hibernacja może nie być dla Ciebie idealna i powinieneś rozważyć pracę z Spring-JDBC jako opakowanie JDBC.
Mądrze zindeksuj bazę danych i użyj poprawnego schematu db. Zastanów się nad użyciem warstwy procedur przechowywanych, ponieważ są one wstępnie skompilowane i zoptymalizowane.
Chciałbym powiedzieć, że w przeszłości miałem do czynienia z systemem (jednym węzłem) na mysql (głównie dostęp tylko do odczytu) z jboss 4.2.1 i udało mi się osiągnąć 2000 równoczesnych użytkownicy
(nie uzyskując natychmiastowego dostępu do otwierania 2000 gniazd na naszym serwerze), ale używając / przeglądając nasz system, używając JBoss Cache i wstępnie ładując do pamięci podręcznej niektóre najczęściej używane dane lub dane, które zdaliśmy sobie sprawę, będą „gorące i popularne „ale nasze rozwiązanie było dobre dla naszej architektury i naszych przepływów,
więc, jak mówię, w tych przypadkach -
Jest więcej wskazówek i wskazówek, ale tak naprawdę zależy to od architektury i przepływów, które musisz mieć w systemie. Powodzenia!
źródło
Dobre pytanie. Prawdopodobnie trudno powiedzieć, które podejście jest najlepsze, ale spróbuję z mojego doświadczenia.
Najlepszym sposobem na skalowanie aplikacji internetowej opartej na Javie jest napisanie jej tak bezstanowo, jak to możliwe (jeśli to możliwe). Umożliwia to skalowanie w poziomie aplikacji, do której można dodać serwery tomcat, jeśli jest więcej współbieżnych użytkowników.
Jednak, jak zauważyłeś, może występować problem z połączeniami z bazą danych. Ale mam pytanie, w jaki sposób otrzymujesz dane? Czy jest generowany przez użytkownika, czy otrzymujesz dane od strony trzeciej? Jest to bardzo ważne, ponieważ jeśli świadczysz usługę dla użytkownika z danymi zebranymi z aplikacji innej firmy (np. FB, Twitter itp.), Możesz śledzić zapisywanie w bazie danych master i replikowanie danych do baz danych slave które są przydzielane do każdej instancji tomcat. Następnie każdy serwer tomcat może uzyskać z własnej bazy danych slave.
Możesz przejść do klastra MySQL, który ma magazyn danych w pamięci. Ale uwaga na to, że aplikacja może wymagać pewnych zmian. Nie
sql joins
są dobrze obsługiwane w klastrze MySQL, chociaż w najnowszej wersji wprowadzono ulepszenia tego samego. Jeśli koszt nie jest czynnikiem, możesz wypróbować Oracle.Rozwiązanie buforowania zdecydowanie poprawi wydajność. Ale wszystko zależy od architektury całej aplikacji. Powinieneś dobrze wiedzieć, kiedy przesłać dane do pamięci podręcznej, a kiedy je zabrudzić (usunąć z pamięci podręcznej).
Jeśli chodzi o rozkład obciążenia w środowisku wieloserwerowym, sugerowałbym użycie równoważenia obciążenia niż użycie Apache do równoważenia obciążenia.
źródło
Obecnie konfiguruję podobny system (na poziomie profesjonalnym) i taki projekt wybrałem:
Pozwoli to uzyskać nadmiarowe, skalowalne rozwiązanie o wysokiej dostępności.
Loadbalancery (na przyzwoitym sprzęcie) z łatwością wyrównają nasycenie nasyconej linii 1 Gb / s każda. Jest to również świetne miejsce do odciążania SSL.
Możesz zapisać informacje o sesji w memcached. W przypadku awarii instancji tomcat inna instancja tomcat może pobrać odpowiednie informacje o sesji, a klienci nic nie zauważą. Nie zapomnij też połączyć tego z lepkimi sesjami. (Aby ograniczyć ruch w sieci)
Klastrowanie Tomcat ma również opcję udostępniania informacji o sesji między klastrami w czasie rzeczywistym, bez korzystania z memcached. Chociaż myślę, że pod względem wydajności, używanie Memcached będzie lepsze.
Jeśli potrzebujesz więcej mocy w którejkolwiek z tych aplikacji:
Nie wiem, jak tworzona jest aplikacja i jakie są duże zasoby zasobów, ale jeśli zauważysz duże obciążenie bazy danych (podczas testów ładowania!), Dodanie pamięci podręcznej między aplikacją a bazą danych może z pewnością znacznie poprawić wydajność. Ale nie zapominaj, że nie wszystko jest możliwe do buforowania, jeśli twoje zapytania są zawsze inne, buforowanie nie pomoże (dużo)
Radzę pobrać VMware Workbench (lub oprogramowanie do wirtualizacji similair) i spróbować stworzyć prostą konfigurację. Bez równoważenia obciążenia i grupowania, tylko podstawy i praca stamtąd. Jeden po drugim dodaj kolejne funkcje (równoważenie, buforowanie, klastrowanie itp.) I upewnij się, że przeprowadziłeś badania na każdy temat, abyś wiedział, że dokonałeś właściwego wyboru.
Jeśli nadal będziesz przeprowadzać te same testy wydajności podczas tego procesu, możesz sam przekonać się, czy użycie X jest lepsze niż użycie Y w konfiguracji lub jaki wpływ będzie miało buforowanie itp.
Ostatecznie taka konfiguracja naprawdę zależy od wymagań aplikacji i jej klientów, wszystko można zrobić na różne sposoby, każdy z własnymi mocnymi i słabymi stronami.
Jakieś pytania?
Powodzenia!
Wesley
źródło