Myśli otwierające
Jak doszedłeś do wniosku, że niektóre części systemu wypadłyby lepiej w innym języku? Czy masz problemy z wydajnością? Jak poważne są te problemy? Jeśli może być szybszy, czy konieczne jest, aby był szybszy?
Asynchronia jednowątkowa
Istnieje kilka pytań i innych zasobów internetowych, które już zajmują się różnicami, zaletami i wadami asynchronii jednowątkowej vs. współbieżności wielu wątków. Interesujące jest przeczytanie o tym, jak działa jednowątkowy model asynchroniczny Node.js, gdy we / wy jest głównym wąskim gardłem, a jednocześnie obsługiwanych jest wiele żądań.
Twisted, Tornado i inne modele asynchroniczne doskonale wykorzystują jeden wątek. Ponieważ wiele programów internetowych ma wiele operacji we / wy (sieć, baza danych itp.), Czas oczekiwania na połączenia zdalne znacznie się zwiększa. To czas, który można poświęcić na wykonywanie innych czynności - takich jak uruchamianie innych wywołań bazy danych, renderowanie stron i generowanie danych. Wykorzystanie tego pojedynczego wątku jest niezwykle wysokie.
Jedną z największych zalet asynchronii jednowątkowej jest to, że zużywa ona znacznie mniej pamięci. W przypadku wykonywania wielu wątków każdy wątek wymaga pewnej ilości zarezerwowanej pamięci. Wraz ze wzrostem liczby wątków rośnie również ilość pamięci wymaganej tylko do istnienia wątków. Ponieważ pamięć jest skończona, oznacza to, że istnieją ograniczenia dotyczące liczby wątków, które można utworzyć w dowolnym momencie.
Przykład
W przypadku serwera WWW udawaj, że każde żądanie ma swój własny wątek. Powiedz, że 1 MB pamięci jest wymagany na każdy wątek, a serwer WWW ma 2 GB pamięci RAM. Ten serwer sieciowy byłby w stanie przetworzyć (w przybliżeniu) 2000 żądań w dowolnym momencie, zanim zabraknie pamięci do przetworzenia.
Jeśli obciążenie jest znacznie wyższe, żądania zajmą bardzo dużo czasu (czekając na zakończenie starszych wniosków) lub będziesz musiał wrzucić więcej serwerów do klastra, aby zwiększyć liczbę możliwych jednoczesnych żądań .
Współbieżność wielu wątków
Współbieżność wielowątkowa polega natomiast na wykonywaniu kilku zadań jednocześnie. Oznacza to, że jeśli wątek zostanie zablokowany w oczekiwaniu na wywołanie bazy danych w celu powrotu, inne żądania mogą być przetwarzane w tym samym czasie. Wykorzystanie wątku jest niższe, ale liczba wykonanych wątków jest znacznie większa.
Kod wielowątkowy jest również znacznie trudniejszy do uzasadnienia. Występują problemy z blokowaniem, synchronizacją i innymi problemami dotyczącymi współbieżności. Asynchronia jednowątkowa nie ma tych samych problemów.
Kod wielowątkowy jest jednak znacznie wydajniejszy w przypadku zadań intensywnie wykorzystujących procesor . Jeśli nie ma możliwości, aby wątek „ustąpił” - tak jak połączenie sieciowe, które normalnie by blokowało - model z jednym wątkiem po prostu nie będzie miał żadnej współbieżności.
Oba mogą współistnieć
Oczywiście oba te elementy nakładają się; nie wykluczają się wzajemnie. Na przykład kod wielowątkowy można zapisać w sposób nieblokujący, aby lepiej wykorzystać każdy wątek.
Dolna linia
Jest wiele innych kwestii do rozważenia, ale lubię myśleć o dwóch takich:
- Jeśli twój program jest powiązany z We / Wy , to asynchronia jednowątkowa prawdopodobnie będzie działać całkiem dobrze.
- Jeśli twój program jest powiązany z procesorem , prawdopodobnie najlepszy będzie system wielowątkowy.
W konkretnym przypadku musisz ustalić, jaki rodzaj pracy asynchronicznej jest wykonywany i jak często te zadania powstają.
- Czy występują na każde żądanie? Jeśli tak, pamięć prawdopodobnie stanie się problemem wraz ze wzrostem liczby żądań.
- Czy te zadania są zlecone? Jeśli tak, musisz rozważyć synchronizację, jeśli używasz wielu wątków.
- Czy te zadania wymagają dużej mocy obliczeniowej procesora? Jeśli tak, to czy pojedynczy wątek jest w stanie nadążyć za obciążeniem?
Nie ma prostej odpowiedzi. Musisz rozważyć, jakie są twoje przypadki użycia i odpowiednio zaprojektować. Czasami lepszy jest asynchroniczny model jednowątkowy. Innym razem wymagane jest użycie wielu wątków w celu osiągnięcia masowego przetwarzania równoległego.
Inne uwagi
Należy również wziąć pod uwagę inne kwestie, a nie tylko wybrany model współbieżności. Czy znasz Erlang lub Clojure? Czy uważasz, że byłbyś w stanie napisać bezpieczny wielowątkowy kod w jednym z tych języków, aby poprawić wydajność swojej aplikacji? Czy przygotowanie jednego z tych języków zajmie dużo czasu i czy język, którego się uczysz, będzie korzystny w przyszłości?
Co powiesz na trudności związane z komunikacją między tymi dwoma systemami? Czy utrzymywanie równolegle dwóch oddzielnych systemów będzie zbyt skomplikowane? W jaki sposób system Erlang odbierze zadania od Django? W jaki sposób Erlang przekaże te wyniki z powrotem do Django? Czy wydajność jest na tyle istotnym problemem, że dodatkowa złożoność jest tego warta?
Końcowe przemyślenia
Zawsze uważałem, że Django jest wystarczająco szybkie i jest używane przez niektóre witryny o dużym natężeniu ruchu. Istnieje kilka optymalizacji wydajności, które można wykonać w celu zwiększenia liczby jednoczesnych żądań i czasu odpowiedzi. Trzeba przyznać, że do tej pory nic nie robiłem z Selerem, więc zwykłe optymalizacje wydajności prawdopodobnie nie rozwiążą żadnych problemów związanych z tymi asynchronicznymi zadaniami.
Oczywiście zawsze pojawia się sugestia, aby rzucić więcej sprzętu na problem. Czy koszt zapewnienia nowego serwera jest tańszy niż koszt opracowania i utrzymania całkowicie nowego podsystemu?
W tym momencie zadałem zbyt wiele pytań, ale taka była moja intencja. Odpowiedź nie będzie łatwa bez analizy i dalszych szczegółów. Jednak umiejętność analizowania problemów sprowadza się do znajomości pytań, które należy zadać, ale… mam nadzieję, że pomogłem na tym froncie.
Moje przeczucie mówi, że przepisywanie w innym języku nie jest konieczne. Złożoność i koszt będą prawdopodobnie zbyt duże.
Edytować
Odpowiedź na działania następcze
Twoje działania następcze przedstawiają kilka bardzo interesujących przypadków użycia.
1. Django działa poza żądaniami HTTP
Twój pierwszy przykład obejmował odczyt tagów NFC, a następnie przeszukanie bazy danych. Nie sądzę, aby pisanie tej części w innym języku było dla ciebie przydatne, ponieważ zapytania do bazy danych lub serwera LDAP będą ograniczone przez sieciowe operacje we / wy (i potencjalnie wydajność bazy danych). Z drugiej strony liczba równoczesnych żądań będzie ograniczona przez sam serwer, ponieważ każde polecenie zarządzania będzie uruchamiane jako osobny proces. Nastąpi czas konfiguracji i porzucania, który wpływa na wydajność, ponieważ nie wysyłasz wiadomości do już uruchomionego procesu. Będziesz jednak mógł wysyłać wiele żądań jednocześnie, ponieważ każde z nich będzie procesem izolowanym.
W tym przypadku widzę dwie ścieżki, które możesz zbadać:
- Upewnij się, że baza danych jest w stanie obsłużyć wiele zapytań jednocześnie z pulą połączeń. (Na przykład Oracle wymaga odpowiedniego skonfigurowania Django
'OPTIONS': {'threaded':True}
.) Mogą istnieć podobne opcje konfiguracji na poziomie bazy danych lub na poziomie Django, które można dostosować do własnej bazy danych. Bez względu na język, w którym piszesz zapytania do bazy danych, będziesz musiał poczekać na powrót tych danych, zanim zaświecisz diody LED. Wydajność kodu zapytania może jednak mieć znaczenie, a ORM Django nie jest błyskawiczny ( ale zazwyczaj wystarczająco szybki).
- Zminimalizuj czas instalacji / porzucania. Miej ciągły proces i wysyłaj do niego wiadomości. (Popraw mnie, jeśli się mylę, ale na tym właśnie koncentruje się twoje pierwotne pytanie.) Czy proces ten jest napisany w Pythonie / Django, czy w innym języku / frameworku został omówiony powyżej. Nie podoba mi się pomysł częstego używania poleceń zarządzania. Czy możliwe jest ciągłe działanie małego fragmentu kodu, który wypycha wiadomości z czytników NFC do kolejki wiadomości, którą Celery następnie czyta i przekazuje do Django? Konfiguracja i porzucenie małego programu, nawet jeśli jest napisany w Pythonie (ale nie w Django!), Powinno być lepsze niż uruchamianie i zatrzymywanie programu Django (ze wszystkimi jego podsystemami).
Nie jestem pewien, jakiego serwera używasz dla Django. mod_wsgi
dla Apache pozwala skonfigurować liczbę procesów i wątków w procesach, które obsługują żądania. Koniecznie dostosuj odpowiednią konfigurację serwera WWW, aby zoptymalizować liczbę żądań serwisowych.
2. „Przekazywanie wiadomości” za pomocą sygnałów Django
Drugi przypadek użycia jest również dość interesujący; Nie jestem pewien, czy mam na to odpowiedzi. Jeśli usuwasz instancje modelu i chcesz operować na nich później, może być możliwe ich serializowanie, JSON.dumps
a następnie deserializacja JSON.loads
. Ponowne odtworzenie grafu obiektowego później (odpytywanie modeli pokrewnych) będzie niemożliwe, ponieważ powiązane pola są wczytywane z bazy danych leniwie, a to łącze już nie istnieje.
Inną opcją byłoby jakoś oznaczyć obiekt do usunięcia i usunąć go tylko na końcu cyklu żądania / odpowiedzi (po obsłużeniu wszystkich sygnałów). Może to wymagać niestandardowego sygnału do wdrożenia tego, zamiast polegać na post_delete
.