#lurkerchangelog / No i dobra Moi Mili, czas na spowiedź! Oto, co spowodowało awarię, która poniedziałek-czwartek (do wczoraj) lagowała system tak że heeej Jak to sie mówi, człowiek uczy sie na błedach…

Temat był wyjątkowo trudny do wykrycia i analizy. Systemy zachowywały się normalnie. Sprawdziłem absolutnie wszystkie możliwe scenariusze: od przeciążenia CPU/RAM (htop), po przeciążenie dysków (iotop), przez analizę ruchu sieciowego, profilowanie pakietów, ograniczenia połączeń: ilości (limit conn), wsadów (body size), timeoutów (w tym rownież proxy_connect_timeout) i tysiąc innych rzeczy. Widziałem ogrom ruchu na GET /socket. Burst-limity załatwiły sprawę, ale problem pozostał. (tu się okazało, że na niektórych urządzeniach, głównie Mac oraz iOS, apka ignoruje timeout miedzy kolejnymi próbami nawiązania połączenia, gdy serwer zamyka socket i próbuje non-stop odnowić połączenie, aż do skutku - co b. mocno mnie zmyliło). Esz, cieżkie to były 3 dni, naprawdę.

Tak więc odpowiadam, co wywaliło cały system. W apkach nie robi się każdorazowo połączenia i rozłączenia z bazą, gdy idzie request (bo to mocno spowalnia, trzeba by wykonywać każdorazowo handshake'a itd.) - zamiast tego korzysta się z tzw. poola, czyli puli, która trzyma określoną liczbę klientów.
const pg = require('pg');
const pool = new pg.Pool(config);
let client = await pool.connect();

await client.release();
Pool wydaje klienta, kiedy trzeba. Po "robocie" klient wraca do poola, gotów do kolejnych akcji. I tak w kółko. Lurker korzysta ze sterownika node-postgres, w którym domyślna liczba owych klientów w poolu wynosi… 10! Co trzeba koniecznie zmienić, podbijając moocnooo w górę. Otóż jakimś nieumyślnym cudem zakomentowałem ten parametr i liczba klientów w poolu spadła do wartości domyślnej, czyli 10. Co powodowało laga, bo jeśli wchodzili nowi ludzie, to musieli czekać aż zwolni się klient: można to przyrównać do stania w kolejce. Masz 10 kas w sklepie i ustawiasz się do jednej z nich i czekasz. 4 workery dają 4 sklepy, w każdym po 10 kas, ale to nadal za malo sklepów i kas - coś jak Carrefour przed świętami (ruch idzie cały czas w górę).

No i to tyle. Przepraszam wszystkich, że dałem ciała. Chochlik w kodzie, jak to sie mowi. Można robić memy, zapraszam! (bana nie będzie!)

Podsumowując, problem był wyjątkowo ciężki do wykrycia. Wiele rzeczy tutaj mnie zmyliło. Jako ciekawostkę dodam, że lurker był w przeszłości dwa razy ddosowany (nawałem pakietów z botneta) i nawet tego userzy nie odczuli za bardzo, bo całość skończyła się po 2 minutach. Dlaczego? Ano dlatego, że lurker podnajmuje hosting u Hetznera (TOP 6 najwiekszych dostawców). Jeśli ktoś rozpoczyna ddos na jakąś maszynę, wpływa to bezpośrednio na stabilność całej sieci u dostawcy, dlatego bardzo sprawnie wycina on na głównym routerze podejrzany ruch (to leży także w jego interesie). Ja natomiast - jako admin (ich klient) - dostaję maila z info, co właśnie sie dzieje i że zaraz zostanie sprawa załatwiona. Jest to bardzo kompleksowa obsługa i bardzo fachowa, monitorowana 24h na dobę. Tak więc na tem moment CloudFlare nie jest potrzebny

Od jutra wracam do kodzenia. Mam sporo zaległości, bo praktycznie cały tydzień w plecy. Ale spokojnie, nadrobimy

41

@Thanos, Duży szacunek za nie zamiatanie pod dywan i podzielenie się.
Można robić memy, zapraszam!
@GzKk, haahaaha! widze, ze jest już nie "press F", tylko "press F5", hahaha! pasuje!
@Thanos, Gratulacje! Super, że udało się zdiagnozować i naprawić problem.

A jak oceniasz pracę z CockroachDB? Warte to to jakiegokolwiek zainteresowania?
@Redlic, powiem tak: na tę chwilę mam tylko 1 node, a żeby skorzystać z przewagi, jaką daje, musiałbym miec min. 3 niezależne serwery.

na ten moment wrażenia są takie.
WADY:
- duuużo wolniejsze od Postgresa,
- o wiele mniej opcji oraz funkcji od PG,
- w tym spora lipa z reversed-indexami dot. pól json (to jest mega spory problem: pewnie zauwazyłeś, ze glowna czy mikro ładują się w 1-2 sek. (1 obrót loadera), a strona tagu (np. /tag/lurkerchange dokladnie 2x dluzej). to jest spowodowane tym, że reversed indexa nie mozna łaczyć z innymi indexami. mega bolączka i ból niesłychany.
ZALETY:
- pełna zgodność sterownika z PG (dla node oraz pozostałych technologii),
- super przejrzysty (out-of-the-box) ui-admin panel: pokazujący wszytkie staty, kwerendy i inne bzdety: to jest MEGA! kozak. super sprawa,
- banalny update (STOP / podmiana 1 pliku EXE / START); gotowe,
- bardzo duża spójność i izolacja danych (to jest baza transakcyjna); Mongo przy tym to tragedia, dlatego mimo ~5x lepszego benchmarku wywaliłem w pizdu.
ZALETY, na które liczę (w przyszłości, bo na razie nie doszliśmy do tego etapu, wiec nie moge powiedzieć, ale jestem pełen nadziei ):
- łatwe skalowanie (dodawanie node'ów jednym kliknieciem),
- 0 downtime'ów (na razie mamy 1 tylko node'a).

moim marzeniem jest mieć 3x serwerki z Cdb. wtedy bedziemy miec - poza mozliwoscią obsługi duuuzego ruchu - także redundancję 100%. (100% uptime, WOW! wreszcie )

na razie lurker jest skromny. jedzie na 1 dedyku (ale za to przyzwoitym), i to w sumie styke, bo obciazenie zasobów prawie zadne
@Redlic, jeszcze tylko dodam, że bardzo mocno wierzę w tę bazę. mam szczerą nadzieję, że w przyszłości da nam nieslychaną przewagę (nad Wykopem oraz pozostalymi serwisami), mogąc obsłużyć nieskończony ruch (oczywiście nie mowie o nakladach finansowych na nowe serwery, a wyłacznie o spójność danych i sensowne działanie).

co z tego, że wykop ma X-set(?) razy większy budżet, i mogą dokladać kolejne serwery, jak ciągle tam coś pada. Ostatnio jest awaria z plusowaniem. nie mozna plynnie plusować.

chcesz lepszy case? prosze bardzo. wejdź proszę tutaj i skrolluj w dół.
https://www.wykop.pl/tag/czkawka/

fajne, nie? (@Anty_Anty o tym pisał ostatnio )

zapętlenie na amen.

baza danych to najwazniejszy element każdej apki. nie ma znaczenia czy jest Node, czy PHP, czy GO, czy cokolwiek. apka to tylko API do bazy. baza jest najwazniejsza. bardzo dlugo wybieralem odpowiednią bazę z nastawieniem na przyszłe problemy, którę (mam nadzieje!!!) juz niedlugo beda mogły wystąpić (daj Boze! ).

czekam na skokowy wzrost popularnosci portalu. jakby co, jestesmy przygotowani (w niecałe 30 min moge odpalić i podpiąć kolejne serwery). tylko to są koszta, a wolałbym (jeśli nie muszę) za wiele nie dokładać …jakby lurker sie samofinansował, to było spoko. juz niebawem pojawi sie pierwszy ambasador portalu z małym
#rozdajo
.

licze, że ruch bedzie rósł powoli, acz systematycznie. gdzie nam sie spieszy
@Shuloch, zobacz proszę tutaj posta powyzej.
Brzmi jak całkiem fajny stack. Pewnie robisz Lurkera, bo w pracy nie masz nowych zabawek, a chcesz je potestować.
Dokładnie tak jest! hahaah!! 200% racji, masz mnie!!

btw. frontend jest na Svelte (w poprzednich firmach PL, gdzie pracowałem React/Vue były "zbyt nowe", aby wdrażać: "panowie, tylko jQuery!!!!", hahaha! a tutaj jeb! Svelte poleciało i nikt mi nie mowi, co mam robić. z Node.js to samo.

ja kodze, jak mi sie podoba, ale ponosząc przy tym pełnię odpowiedzialności, jak coś sie wysypie. nie ma, że idę na konsultację do seniora i rozmawiamy, co jest nie tak. jak się zgrzeje, to wszystko jest na moich ramionach. troche to obciążające z jednej strony, ale przyjemność z kodzenia nie do opisania. sam decyduje i nie musze nikogo przekonywać. WOW!

taka ciekawostka jeszcze: Node.js jest mega szybki, nie tylko, że v8 jest wydajny, ale też dlatego, ze np. w przeciwienstwie do PHP jest nie-blokowy. zasuwa jak traktorek
Pokaż spoilerhm… czy traktorki zasuwają??? :D
@Shuloch, przed wdrożeniem na proda robiłem bardzo dużo sporo różnych testów. v1 było w calości na MongoDB (w Redisie mialem tylko sesję przechowywaną).

powiem tak: Mongo na testach wypadło rewelacyjnie, a w praktyce takich żal i płacz, że chciałem zawijać serwis. dzis każdemu odradzam. potem wpadło mi Cdb (obecnie). na testach rewelacja (niczym Mongo, huehue )… a w praktyce? jak na razie (po niecałym miesiacu) takze spoko. niemniej życie zweryfikuje.

jesli okaże się lipa, zmienimy. mamy jeszcze ten czas, że możemy w locie zmieniać (apka padnie na jedna noc, i bedzie nowa baza: tak jak przy przejsciu z v1 do v3). no trudno. lurker to pole do testów, bawię się nim dużo, ale o to w tym chodzi.

to nie jest apka enterprise, że musi mieć 100% uptime i zero bugów. ludzie widzą, że za nim nie stoi duza firma z zespołem devów i help-deskiem 24h. czesto wywala błedy, ale te naprawiam od ręki
@Thanos, nice. To pewnie jeszcze zagadam Cie kiedyś o wrażenia. Podobną ideę jak Cdb ma YugabyteDB, ale nie miałem okazji przetestować.

Szczerze mówiąc, nie wierzę w cuda, że baza ma skalowalność na read i write, ACID, dobry performance i nie wiadomo co jeszcze. Zawsze jest coś za coś. Mimo wszystko uważam, że wynalazki w stylu Cdb są ciekawe i jak się ma okazję warto je sprawdzić.
w przeciwienstwie do PHP jest nie-blokowy
Chodzi o nie blokowanie wątku aplikacji operacjami I/O itp. (Reactive)? Tutaj chyba duża zasługa jest sterowników do bazy danych, które nie są blokujące. Ciekawie zapowiadają się też green threads i fibers, które obiecują że pozwolą programować w sposób sekwencyjny zachowując wydajność zbliżoną do reaktywnego stacka. Osobiście czekam z niecierpliwością.
mogąc obsłużyć nieskończony ruch
Trzymam kciuki, ale mam obawy. Jeśli Cdb używa transakcji rozproszonych to performance wcale nie musi być zadowalający. Szczególnie jakby weszły jakieś query, które robią joiny na danych rozrzuconych między różnymi node'ami. Chyba że na wszystkich node'ach jest zawsze komplet danych, ale wtedy rozmiar dysku blokuję nieskończoność.
@Shuloch, YugabyteDB testowalem to! To jest kopia Cassandry. v2 miała być na Yuga (ostre dyskusje z lisqiem swojego czasu o to toczyłem). ale… idea upadła. ogólnie zamysł dobry, jako baza, architektonicznie, ale wyłącznie dla prostych obiektów. jako ciekawostka: v2 została napisana w Yuga, ale potem przepisałem na MySQL
Chodzi o nie blokowanie wątku aplikacji
tak, wlasnie chodzi o to. PHP blokuje wątek i jest wykonywany do czas zakończenia. w JS (v8) rozwiązali to poprzez event loopa (nadal js jest jednowątkowy, ale pseudo-asynchroniczny: wszystkie operacje wstawiane są do kolejki i tam mielone). w efekcie uzyskano obłędny performance dodając jeden poziom abstrakcji więcej. Ogólnie JS ma w stosunku do PHP 3-6x lepszy benchmark. Do pythona ponad 10x tyle. Miłe zaskoczenie, bo naprawdę śmiga
Szczególnie jakby weszły jakieś query, które robią joiny
w v3 nie ma ani jednego joina (porobiłem relacje, ale nie mam zmiaru z nich korzystać, żeby podkręcić jeszcze bardziej wydajność ). bardziej relacje zamierzam wykorzystywać do celów analitycznych w przyszłości, ze puszczam query na noc i zostawiam kompa ogólnie wszystko bardzo mocno zoptymalizowałem. inna ciekawostka jest taka, że wszystko pola są precomputed, czyli nic nie jest liczone w locie (np. count(1)), ale wartość jest obliczana i zapisywana w bazie i potem tylko szybki read leci.

na razie sprawdzam, jak bedzie. to jest technologia nietestowana przeze mnie na produkcji, wiec moze coś wyjsc po drodze. plus jest taki, że jak sie okaże lipa, to mogę błyskawicznie przeskoczyć na Postgresa, bo API jest 100% identyczne (w drugą strone by nie przeszło, bo PG ma wiecej funkcji).
@Thanos,
w v3 nie ma ani jednego joina
Implementujesz CQRS i masz pod każdy widok dedykowana tabele? Ciężko mi inaczej wyobrazić sobie konsystencję w relacyjnej bazie danych, ale może mam za słaba wyobraźnię^^
@Shuloch, nope są relacje. ale apka nie używa joinów. jak pobieram posty, to cyk, pobieram posty (np. od najnowszych). następnie zczytuję autorów (userId) i osobno pobieram userów. zwracam osobno userów i posty. i na froncie to łączę (po stronie klienta). zero przeciążeń na backendzie + zero joinów, a jedynie proste selecty
@Thanos, ok, czyli zamiast 1 requesta do backendu to lecą 3 i GUI osobno obsługuje ładowanie tych danych. Zgadza się?
@Shuloch, zamiast jednego z joinem, lecą 2 (joiny nie są za darmo), wolę obciążyć szybkiego Node'a (a workerów z wątkami można miec bez liku) niż serwer bazodanowy, który jest o wiele cenniejszy.

wysyłam na koniec responda: obiekt, gdzie sa osobno posty (wszystkie na płasko, nie drzewo: że parent > dziecko > wnuczek itd. -- wszystko na płasko: post1a, post1b, post2a, post1c, post2d… etc. - i na płasko userów i wszystko sie sklada na froncie)
Szacun @Thanos Ale pamiętaj, pewnego dnia Bóg wyłączy wtyczkę
@Paker, pamiętam, pamiętam
@Thanos, Za cholerę nic nie rozumiem, ale bardzo doceniam że wyjaśniłeś userom co było nie halo. Dobrego weekendu!
@Thanos,
Ano dlatego, że lurker podnajmuje hosting u Hetznera (TOP 6 najwiekszych dostawców).
tez czasami używam i jest to jeden z najlepszych
Node.js to po prostu potwór wydajnościowy
haha nie przesadzaj
@tenji, a jakie zdanie masz odnosnie Node'a? i w czym kodzisz, że go przebija? chyba tylko GO wydaje się mocniejszy (nie sprawdzałem, ale przeglądałem benchmarki).

na pewno Python, PHP i Java nie mają podjazdu.
@Thanos, Jesteś Wielki, Szefie
@mysliwiec, dzieki! najwazniejsze, ze problem został naprawiony. duch motywacyjny we mnie nie został złamany! (nie było nawet blisko! )
@Thanos, Jesteś Twardzielem. Wszystko w pojedynkę…szacun
@Thanos, brakuje mi tylko lupki aby po tagach szukać, albo ogólnie szukać
@mysliwiec, lista tagów ma szanse pojawic sie juz na ten weekend
@Thanos, a zwykła wyszukiwarka?
@mysliwiec, wyszukiwarka treści? że szukasz po treści posta konkretnych wpisów?

Wpis został usunięty przez autora

@Dyrygent, musiałem wyjaśnić, bo ludzie czekali z mega-ciekawością, co mnie tak mocno zatkało.. potężny Thanos padł na kolana (ale tylko chwilowo - bo sobie sam strzelił w stope / AUĆ! )
@Thanos, F5 respect:D Zajebiście ojciec, podziwiam pracowitość i wytrwałość.
@LizardKing, nie z takich opresji sie wychodziło

…akurat nigdy wczesniej tak nie dalem sie zaskoczyć przez buga, stad obskoczyłem srogi wpierdziel, ale liże rany, jest ok
@Thanos, z ciekawości - do jakiego rozmiaru podbiłeś pulę połączeń? I czy lurker chodzi na 1 instancji apki, czy jest jakaś redundancja?
@Shuloch, aktualnie redundacja jest, ALE taka słaba. bo sprowadza sie do 1 serwera. na nim chodzą 4 workery apki. jest to klasycznie zrobione przez load balancer (
least_conn
wyłącznie do zdrowych node'ów).

moim marzeniem jest mieć min. 5 serwerów: mam juz wszystko rozplanowane i rozpisane. nie ze wzgledu na zasoby (bo nadal CPU jest w okolicach 2%: Node.js to po prostu potwór wydajnościowy), ale ze wzgledu na redundancje.

Wszystko jest tak przygotowane, że bedzie mozna nieskończenie skalować. Baza danych to CockroachDB, czyli można w bardzo prosty sposób podpinać kolejne serwery, i skalować pod sufit. Ogranicza nas tylko wyobraźnia i budżet licze, ze pewnego dnia (juz niedlugo) dojdziemy do tego poziomu. wtedy dopiero bedzie ten stack mogl sie wykazać (bo teraz to mogłem postawić buddypress na wordpressie albo phpBB (by Przemo) na zwykłym hostingu i to samo by było…

prawdę mówiąc, pisząc apkę byłem zorientowany na maksymalny ruch (wiekszy nawet niż FB czy Reddit: to sie nie ziści, ale chodzi o założenia teoretyczne: chciałem potestowac nowe podejscie i sprawdzic nowe rzeczy.

po prostu w przypadku sukcesu (a pewnego dnia ruch zacznie drastycznie rosnąć, nie chce dojść w pewnym momencie do ściany i albo pójść mocno w koszta, albo okryć się wstydem, że jest problem, którego nie umiem naprawić).

(@patryk1303: dałeś plusa, wiec tez wołam)
@Thanos, CockroachDB? Po tekście o node-postgres myślałem, że na postgresie stoi to (chociaż spodziwałem się jakiegoś mongoDB ;)). Nie słyszałem o tej bazie wcześniej. Wygląda na fajną zabawkę. Czy w praktyce od strony użytkownika (tzn. apki, która tam pisze/czyta z niej) różnica jest jakaś duża w porównaniu do Postgresa?
bo nadal CPU jest w okolicach 2%: Node.js to po prostu potwór wydajnościowy
Może się mylę, ale tutaj chyba nie ma żadnych skomplikowanych obliczeń, więc użycia CPU zawsze spodziewałbym się niskiego (musiałby być naprawdę ogromny ruch). Prędzej jakieś I/O mogłoby trzymać apkę.

Brzmi jak całkiem fajny stack. Pewnie robisz Lurkera, bo w pracy nie masz nowych zabawek, a chcesz je potestować.