Jak efektywny może być Meteor, dzieląc się ogromną kolekcją wśród wielu klientów?

Wyobraź sobie następujący przypadek:

  • 1,000 klienci są podłączeni do strony Meteor wyświetlającej zawartość kolekcji "Somestuff".

  • "Somestuff" to kolekcja licząca 1000 pozycji.

  • Ktoś wstawia nowy przedmiot do kolekcji" Somestuff "

Co się stanie:

  • Wszystkie Meteor.Collections na klientach zostaną zaktualizowane, tzn. wstawianie przekazane do wszystkich z nich (co oznacza, że jedna wiadomość wstawiania wysłana do 1000 klienci)

Jaki jest koszt procesora dla serwera, aby określić, który klient musi zostać zaktualizowany?

Czy to prawda, że tylko wstawiona wartość zostanie przekazana do klientów, a nie cała lista?

Jak to działa w prawdziwym życiu? Czy są dostępne jakieś benchmarki lub eksperymenty o takiej skali?
Author: senfo, 2012-10-29

4 answers

Krótka odpowiedź jest taka, że tylko nowe dane są wysyłane w dół przewodu. Oto jak to działa.

Istnieją trzy ważne części serwera Meteor, które zarządzają subskrypcji: funkcja publish , która definiuje logikę tego, co dane, które dostarcza abonament; Mongo driver , który ogląda bazy danych dla zmian; oraz pole scalania , które łączy wszystkie aktywnych abonamentów klienta i wysyła je przez sieć do na klient.

Publikuj funkcje

Za każdym razem, gdy klient Meteor subskrybuje kolekcję, serwer uruchamia funkcja publikowania . Zadaniem funkcji publish jest ustalenie zbioru dokumentów, które klient powinien posiadać i przesłać do każdego dokumentu do skrzynki połączeniowej. Uruchamia się raz dla każdego nowego klienta subskrybującego. Ty może umieścić dowolny JavaScript, który chcesz w funkcji publikowania, takich jak dowolnie skomplikowana Kontrola dostępu za pomocą this.userId. The publish funkcja wysyła danych do pola scalania poprzez wywołanie this.added, this.changed oraz this.removed. Zobacz też pełna dokumentacja publikacji dla więcej szczegółów.

Większość funkcji publikowania nie musi się wygłupiać z niskimi poziomami added, changed i removed API. Jeśli funkcja publish zwróci Mongo kursor, Serwer Meteor automatycznie łączy wyjście Mongo kierowca (insert, update, i removed wywołania zwrotne) na wejście merge box (this.added, this.changed i this.removed). Jest całkiem zgrabna. że możesz zrobić wszystkie Kontrola uprawnień z góry w funkcji publikowania i następnie bezpośrednio podłącz sterownik bazy danych do pola scalania bez żadnego użytkownika kod na drodze. A kiedy autopublish jest włączony, nawet ten mały kawałek jest Ukryty: serwer automatycznie ustawia zapytanie dla wszystkich dokumentów w każdym kolekcja i popycha je do pola scalania.

Z drugiej strony, nie ograniczasz się do publikowania zapytań do bazy danych. Na przykład możesz napisać funkcję publikowania, która odczytuje pozycję GPS z urządzenia wewnątrz Meteor.setInterval, lub sonduje starsze REST API z innego serwisu internetowego. W takich przypadkach emitujesz zmiany w połącz pole wywołując low-level added, changed i removed DDP API.

Kierowca Mongo

Mongo driver ' s zadaniem jest obserwowanie bazy danych Mongo pod kątem zmian w zapytania NA ŻYWO. Zapytania te działają w sposób ciągły i zwracają aktualizacje jako wyniki zmieniają się poprzez wywołanie added, removed, i changed wywołania zwrotne.

Mongo nie jest bazą danych w czasie rzeczywistym. Tak więc sondaże kierowców. Utrzymuje Kopia w pamięci ostatniego wyniku zapytania dla każdego aktywnego zapytania. On każdy cykl sondażowy porównuje nowy wynik z poprzednim zapisanym wynik, obliczając minimalny zestaw added, removed, oraz changed zdarzenia opisujące różnicę. W przypadku rejestracji wielu rozmówców wywołania zwrotne dla tego samego zapytania NA ŻYWO, sterownik ogląda tylko jedną kopię zapytanie, wywołanie każdego zarejestrowanego połączenia zwrotnego z tym samym wynikiem.

Za każdym razem, gdy serwer aktualizuje kolekcję, kierowca przelicza każdy live query on that collection (przyszłe wersje Meteor ujawnią skalowanie API w celu ograniczenia, które zapytania NA ŻYWO przeliczają się po aktualizacji.) The sterownik również sonduje każde zapytanie na żywo na 10 sekund, aby złapać poza-pasmowe aktualizacje bazy danych, które ominęły Serwer Meteor.

The merge box

Zadanie merge box polega na łączeniu wyników (added, changed oraz removed wywołania) wszystkich aktywnych funkcji publikowania klienta w jednym dane strumień. Dla każdego podłączonego klienta istnieje jedno pole scalania. Posiada kompletna kopia minimongo cache klienta.

W twoim przykładzie z pojedynczą subskrypcją, pole scalania jest zasadniczo przelot. Ale bardziej złożona aplikacja może mieć wiele subskrypcje, które mogą się pokrywać. Jeśli dwie subskrypcje ustawią ten sam atrybut w tym samym dokumencie, pole scalania decyduje, która wartość ma pierwszeństwo i wysyła to tylko do klienta. Nie ujawniliśmy API dla ustawienie priorytetu subskrypcji jeszcze. Na razie priorytetem jest w zależności od zamówienia klient zapisuje się do zbiorów danych. Pierwszy abonament robi Klient ma najwyższy priorytet, drugi abonament jest następny najwyższy, i tak dalej.

Ponieważ pole merge przechowuje stan klienta, może wysłać minimum ilość danych, aby każdy klient był na bieżąco, bez względu na publikację funkcja go karmi.

Co się dzieje na aktualizacji

Więc teraz ustawiliśmy scenę dla Twojego scenariusz.

Mamy 1000 połączonych klientów. Każdy subskrybuje ten sam live Mongo query (Somestuff.find({})). Ponieważ zapytanie jest takie samo dla każdego klienta, Sterownik jest uruchamiam tylko jedno zapytanie na żywo. Istnieje 1000 aktywnych skrzynek scalających. Oraz funkcja publikowania każdego klienta zarejestrowała added, changed, oraz removed na tym zapytaniu na żywo, które trafia do jednego z pól scalania. Nic innego nie jest połączone z polami scalającymi. Najpierw kierowca Mongo. Gdy jeden z klientów wstawia nowy dokument w Somestuff, uruchamia rekomputację. Mongo driver Zapytanie o wszystkie dokumenty w Somestuff, porównuje wynik do poprzedni wynik w pamięci, stwierdza, że istnieje jeden nowy dokument, a połączenia każdego z 1000 zarejestrowanych połączeń insert.

Następnie funkcje publikowania. Niewiele się tu dzieje: każdy z 1000 insert wywołań wypycha dane do pola scalania przez wywołanie added.

Na koniec każde pole scalania sprawdza te nowe atrybuty pod kątem its Kopia pamięci podręcznej klienta. W każdym przypadku stwierdza się, że wartości nie są jeszcze na kliencie i nie cienią istniejącej wartości. Więc pole merge emituje komunikat DDP DATA na połączeniu SockJS z jego klienta i aktualizuje jego kopię w pamięci po stronie serwera.

Całkowity koszt procesora to koszt zróżnicowania jednego zapytania Mongo, plus koszt 1000 skrzynek połączeniowych sprawdzających stan swoich klientów i konstruujących nowe Ładunek wiadomości DDP. Jedyne dane przepływające przez przewód to single Obiekt JSON wysłany do każdego z 1000 klientów, co odpowiada nowemu dokument w bazie danych, plus jeden komunikat RPC do serwera z klient, który wykonał oryginalną wkładkę.

Optymalizacje

Oto, co na pewno zaplanowaliśmy.
  • Bardziej wydajny sterownik Mongo. My zoptymalizowano sterownik w 0.5.1 uruchamianie tylko jednego obserwatora na osobne zapytanie.

  • Nie każda zmiana DB powinna wywołać rekomputacja zapytania. My może wprowadzić pewne zautomatyzowane ulepszenia, ale najlepszym podejściem jest API pozwala to programiście określić, które zapytania mają być ponownie uruchamiane. Na przykład, jest oczywiste dla programisty, że wstawianie Wiadomości do jeden czat nie powinien unieważniać zapytania na żywo dla wiadomości w drugi pokój.

  • Sterownik Mongo, funkcja publikowania i pole scalania nie muszą być uruchamiane w tym samym procesie, a nawet na tej samej maszynie. Niektóre aplikacje run complex live zapytań i potrzeba więcej procesora do oglądania bazy danych. Inne mają tylko kilka odrębnych zapytań (wyobraź sobie silnik bloga), ale prawdopodobnie wielu podłączonych klientów-potrzebują one więcej procesora do scalania pudełka. Rozdzielenie tych elementów pozwoli nam skalować każdy kawałek niezależnie.

  • Wiele baz danych obsługuje wyzwalacze, które uruchamiają się, gdy wiersz jest aktualizowany i podaj stare i nowe wiersze. Dzięki tej funkcji sterownik bazy danych może zarejestrować WYZWALACZ zamiast ankiety na zmiany.

 119
Author: debergalis,
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-03-07 23:19:01

Z mojego doświadczenia wynika, że korzystanie z wielu klientów podczas dzielenia się ogromną kolekcją w Meteorze jest zasadniczo niewykonalne, począwszy od wersji 0.7.0.1. Postaram się wyjaśnić dlaczego.

Jak opisano w powyższym poście, a także w https://github.com/meteor/meteor/issues/1821 serwer meteor musi przechowywać kopię opublikowanych danych dla każdego klienta w polumerge . To właśnie pozwala na magię meteorów, ale także powoduje, że wszelkie duże wspólne bazy danych są wielokrotnie przechowywane w pamięci procesu węzła. Nawet przy zastosowaniu ewentualnej optymalizacji dla zbiorów statycznych, takich jak w (czy istnieje sposób, aby powiedzieć meteorowi, że zbiór jest statyczny (nigdy się nie zmieni)?), doświadczyliśmy ogromnego problemu z wykorzystaniem procesora i pamięci procesu węzła.

W naszym przypadku publikowaliśmy każdemu klientowi zbiór 15 tysięcy dokumentów, który był całkowicie statyczny. Problem polega na tym, że kopiowanie tych dokumentów do skrzynki merge klienta (w pamięci) po połączenie zasadniczo doprowadziło proces węzła do 100% CPU na prawie sekundę i spowodowało duże dodatkowe wykorzystanie pamięci. Jest to z natury nie do przecenienia, ponieważ każdy łączący się klient powali serwer na kolana (a jednoczesne połączenia będą blokować się nawzajem), a zużycie pamięci wzrośnie liniowo w liczbie klientów. W naszym przypadku każdy klient powodował dodatkowe ~60MB pamięci, mimo że przesyłane surowe dane wynosiły tylko około 5MB.

W naszym sprawa, ponieważ kolekcja była statyczna, rozwiązaliśmy ten problem wysyłając wszystkie dokumenty jako plik .json, który został gzipowany przez nginx i ładując je do anonimowej kolekcji, co skutkowało tylko ~ 1MB transferem danych bez dodatkowego PROCESORA lub pamięci w procesie węzła i znacznie szybszym czasem ładowania. Wszystkie operacje na tej kolekcji były wykonywane przy użyciu _idS ze znacznie mniejszych publikacji na serwerze, co pozwoliło zachować większość zalet Meteor. Pozwoliło to aplikacji na skaluj do wielu innych klientów. Ponadto, ponieważ nasza aplikacja jest głównie tylko do odczytu, dodatkowo poprawiliśmy skalowalność, uruchamiając wiele instancji Meteor za nginx z równoważeniem obciążenia (choć z jednym Mongo), ponieważ każda instancja węzła jest jednowątkowa.

Jednak problem dzielenia się dużymi, zapisywalnymi kolekcjami pomiędzy wielu klientów jest problemem inżynieryjnym, który musi zostać rozwiązany przez Meteor. Prawdopodobnie istnieje lepszy sposób niż przechowywanie kopii wszystkiego dla każdego klienta, ale wymaga to poważnego przemyślenia jako problemu systemów rozproszonych. Obecne problemy z masowym wykorzystaniem procesora i pamięci po prostu nie będą skalowane.

 29
Author: Andrew Mao,
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
2017-05-23 12:09:34

Eksperyment, którego możesz użyć, aby odpowiedzieć na to pytanie:

  1. Zainstaluj test meteor: meteor create --example todos
  2. uruchom go pod Webkit inspector (WKI).
  3. zbadaj zawartość XHR wiadomości poruszających się po przewodzie.
  4. zauważ, że cały zbiór nie jest przesuwany po drucie.

Aby dowiedzieć się, jak używać WKI, zapoznaj się z tym artykułem. To trochę nieaktualne, ale w większości nadal aktualne, szczególnie w przypadku tego pytania.

 4
Author: javajosh,
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-08-24 20:36:21

To jest jeszcze rok i dlatego myślę, że wiedza sprzed"Meteor 1.0", więc może coś się znowu zmieniło? Wciąż się tym zajmuję. http://meteorhacks.com/does-meteor-scale.html prowadzi do "jak skalować meteoryt?"artykuł http://meteorhacks.com/how-to-scale-meteor.html

 3
Author: MistereeDevlord,
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
2014-12-05 00:39:37