Rails 8 na produkcji: stos Solid, po sześciu miesiącach
Gdy Rails 8 wyszło, byłem entuzjastyczny wobec stosu „Solid” bez-Redisa i tezy frameworka jednej osoby. Teraz uruchamiałem go na produkcji przez sześć miesięcy. Oto uczciwa retrospektywa: gdzie dostarczył, gdzie były szorstkie krawędzie i czy uproszczenie wytrzymało pod prawdziwym obciążeniem.
Gdy Rails 8 wyszło, pisałem entuzjastycznie o jego tezie: zwiniętym stosie bez-Redisa — Solid Queue dla
zadań, Solid Cache dla cache, wszystko w Postgresie — plus Kamal do wdrożenia, sumującym się do kompletnej
ścieżki od rails new do produkcji, którą jedna osoba mogła zbudować i uruchamiać. Entuzjazm przy wydaniu
jest jednak tani. Uczciwym testem jest życie z tym, więc oto retrospektywa, którą mogę napisać dopiero teraz:
sześć miesięcy uruchamiania stosu Solid na prawdziwej produkcji, pod prawdziwym obciążeniem. Gdzie
uproszczenie naprawdę dostarczyło? Gdzie były szorstkie krawędzie, które blask startu ukrył? I czy obietnica
„nie potrzebujesz Redisa” wytrzymuje, gdy niesie twój faktyczny ruch? To wyciągnięte lekcje, napisane z drugiej
strony entuzjazmu.
Co naprawdę dostarczyło
Najpierw dobra wiadomość, bo to większa część: rdzenna obietnica wytrzymała. Uruchamianie zadań i cache w Postgresie, bez Redisa w stosie, nie było kompromisem, którego żałowaliśmy przez sześć miesięcy — było uproszczeniem, którym twierdziło, że jest, a korzyści były realne i codzienne:
- Jeden system mniej do operowania, i czujesz to ciągle. Brak osobnego Redisa do provisionowania, monitorowania, zabezpieczania, archiwizowania i rozumowania podczas incydentu. Za każdym razem, gdy coś poszło źle, nieobecność drugiego magazynu danych znaczyła jedno miejsce mniej do sprawdzenia i jedną rzecz mniej, która mogła być przyczyną. Prostota operacyjna nie jest abstrakcyjna; pokazuje się za każdym razem, gdy operujesz systemem.
- Transakcyjne kolejkowanie po cichu wyeliminowało klasę błędu. Ponieważ zadania żyją w tej samej bazie, zakolejkowanie zadania w tej samej transakcji co zmiana danych, która je wyzwala, znaczy, że zatwierdzają się razem albo wcale. Stara niespójność „rekord zapisał się, ale zadanie się nie zakolejkowało” (albo odwrotnie) po prostu przestała się dziać. Nie musieliśmy naprawiać tych błędów; nie mogły wystąpić.
- Jedna kopia, jeden zestaw narzędzi, jeden model mentalny. Zadania i cache archiwizowane z bazą, możliwe do inspekcji SQL-em, którego już używamy. Debugowanie utkniętego zadania znaczyło odpytanie tabeli, nie uczenie się narzędzi introspekcji osobnego systemu. Zjednoczony model mentalny to realna, trwała redukcja obciążenia poznawczego.
Dla zdecydowanej większości tego, o co go prosiliśmy, stos Solid był dokładnie tym, co reklamowano, i sześć miesięcy później sięgnąłbym po niego znów bez wahania. Twierdzenie „nie potrzebujesz Redisa” jest, dla normalnej aplikacji produkcyjnej, prawdziwe.
Szorstkie krawędzie
Uczciwość wymaga drugiej strony, bo żaden stos nie jest od nich wolny, a entuzjazm startu naturalnie te przemilczał. Szorstkie krawędzie, w które faktycznie uderzyliśmy:
- Baza robi więcej, i musisz ją obserwować. Przeniesienie zadań i cache do Postgresa znaczy, że Postgres niesie obciążenie, którego wcześniej nie — odpytywanie i tłuczenie kolejki zadań, odczyty i zapisy cache — wszystko na tej samej bazie obsługującej twoje zapytania aplikacji. Dla nas było dobrze w granicach pojemności, ale to obciążenie, które musisz monitorować, bo ciężki skok zadań teraz pokazuje się jako obciążenie twojej głównej bazy, nie na osobnym Redisie, o którym mógłbyś rozumować w izolacji. Uproszczenie wymienia dwa systemy, które obserwujesz osobno, na jeden system, który musisz obserwować staranniej.
- Wydajność cache to inny profil. Solid Cache, będąc opartym na bazie/dysku, a nie w pamięci, ma inne charakterystyki opóźnienia niż Redis. Dla większości naszego cache’owania było całkowicie w porządku — a znacznie większa pojemność znaczyła, że mogliśmy cache’ować więcej. Ale dla najgorętszych, najbardziej-wrażliwych-na-opóźnienie ścieżek cache zauważyliśmy różnicę i musieliśmy być przemyślani co do tego, co cache’owaliśmy gdzie. To nie jest wymienny równoważnik wydajności do tego w pamięci; to inny punkt na krzywej, i musisz wiedzieć, które ścieżki faktycznie się tym przejmują.
- Konserwacja tabel jest realna. Ukończone zadania i wygasłe wpisy cache akumulują się, a sprzątanie musi faktycznie działać. Mieliśmy jeden incydent wcześnie, gdzie wzrost tabeli zadań pełzł w górę, bo nie daliśmy sprzątaniu dość uwagi — samozadany, łatwo-naprawialny problem, ale przypomnienie, że „zadania w bazie” znaczy, że higiena tabel bazy jest teraz częścią twojej rutyny operacyjnej.
Żadne z tych nie były czynnikami dyskwalifikującymi, i wszystkie były zarządzalne — ale to rzeczy, których opis z dnia wydania (włącznie z moim) nie roztrząsał, i to, na co faktycznie wydajesz uwagę, gdy jest na produkcji.
Pytanie, które wszyscy zadają: czy tęskniliśmy za Redisem?
Uczciwa odpowiedź: dla tej aplikacji nie — i to zaskoczyło nawet mnie trochę. Wchodząc, część mnie spodziewała się uderzyć w ścianę, gdzie podejście oparte na bazie nie nadąży i będziemy musieli reintrodukować Redisa. Nie. Nasze wolumeny zadań i potrzeby cache, które są znaczne, ale nie ekstremalne, siedziały wygodnie w granicach tego, co Postgres obsługuje, a prostota operacyjna była warta więcej niż marginalna wydajność, którą Redis by dodał. Przypadki, gdzie naprawdę wciąż chcesz Redisa, to te, które oznaczyłem przy zapowiedzi — ekstremalna przepustowość zadań, ścieżka cache naprawdę potrzebująca opóźnienia w pamięci — a uczciwym odkryciem po sześciu miesiącach jest to, że większość aplikacji, włącznie z naszą, nigdy faktycznie nie uderza w te progi. Odruch dodawania Redisa był, dla nas, dokładnie instynktem przeinżynierowania, który stos Solid zbudowano, by wycofać. Nie potrzebowaliśmy go, a niemienie go uczyniło wszystko prostszym.
Co powiedziałbym komuś zaczynającemu teraz
Wydestylowana rada z sześciu miesięcy produkcji, dla kogoś ważącego stos Solid na nowej aplikacji Rails 8:
- Domyślnie go. Dla normalnej aplikacji stos Solid bez-Redisa to właściwy punkt startowy i bardzo prawdopodobnie go nie przerośniesz. Zacznij prosto; zawsze możesz dodać Redisa później, jeśli zmierzony limit cię zmusi.
- Monitoruj obciążenie bazy od pierwszego dnia. Skoro zadania i cache teraz ją dzielą, obserwuj obciążenie bazy i wiedz, że wyjścia awaryjne istnieją (osobna baza kolejki, cache pamięci dla konkretnej gorącej ścieżki) na wypadek, gdybyś ich kiedykolwiek potrzebował.
- Ustaw sprzątanie, zanim go potrzebujesz. Uczyń sprzątanie zadań i cache częścią swojej konfiguracji, nie refleksją po fakcie, by wzrost tabel nigdy nie stał się incydentem.
- Nie reintrodukuj Redisa wyprzedzająco. Opieraj się przyzwyczajeniu dodawania go „na wszelki wypadek”. Czekaj, aż masz prawdziwy, zmierzony powód — a możesz całkiem nigdy nie mieć.
Werdykt
Sześć miesięcy uruchamiania stosu Solid Rails 8 na produkcji zamieniło entuzjazm z dnia wydania w ustalony, uczciwy werdykt: rdzenna obietnica wytrzymała. Zadania i cache w Postgresie bez Redisa dostarczyły uproszczenie operacyjne, którym twierdziły — jeden system mniej do operowania (czuty za każdym razem, gdy go operujesz), transakcyjne kolejkowanie po cichu eliminujące klasę błędu spójności i jedna kopia, jeden zestaw narzędzi, jeden model mentalny. Szorstkie krawędzie są realne, ale zarządzalne: baza niesie więcej obciążenia, które musisz monitorować, profil oparty na dysku Solid Cache różni się od Redisa w pamięci na najgorętszych ścieżkach, a konserwacja tabel zadań/cache jest teraz częścią twojej rutyny. Pytanie, które wszyscy zadają — czy tęskniliśmy za Redisem? — odpowiedziało się samo: dla normalnej aplikacji ze znacznymi-ale-nie-ekstremalnymi potrzebami nie, a próg, gdzie naprawdę byś tęsknił, był tym, w który my (jak większość aplikacji) nigdy nie uderzyliśmy, co jest dokładnie odruchem przeinżynierowania, który stos Solid zbudowano, by wycofać. Więc rada to domyślnie stos Solid, monitoruj obciążenie bazy od początku, ustaw sprzątanie wcześnie i nie reintrodukuj Redisa, dopóki zmierzony limit faktycznie cię nie zmusi. Teza frameworka jednej osoby, testowana wobec prawdziwej produkcji, a nie startowego dema, wytrzymuje — i to najmocniejsza rzecz, jaką mogę o niej powiedzieć.