Goodbye lighttpd

Do niedawna korzystałem na prywatnych gratach z lighttpd jako serwera WWW. Lekki, fajny, składnia pliku konfiguracyjnego powiedzmy perlowa, działał. Niby wszystko OK, ale… Raczej nie jest wykorzystywany w różnych nowych projektach. Jeśli ktoś daje narzędzia czy instrukcje, to raczej można się nie spodziewać znalezienia wersji dla lighttpd.

W międzyczasie troche bliżej miałem okazję zetknąć się z nginx. Zrobił na mnie bardzo dobre wrażenie. Dla kilku vhostów bardziej przejrzysty konfig, nieźle wspierany w dokumentacji różnych projektów (apache to to nie jest, ale jest dobrze). Gwoździem do trumny dla lighttpd okazał się brak wsparcia dla HTTP/2, a nawet brak planów w tym zakresie. I łatwość włączenia obsługi HTTP/2 na nginx. Wystarczy jedna dyrektywa w pliku konfiguracyjnym (przy odpowiednio nowej wersji nginx – jest w backportach debianowych). Trochę na zasadzie „wykorzystać, nie wykorzystać, możliwość mieć można”.

Nic dziwnego, że pojawił się pomysł przesiadki na prywatnych gratach z lighttpd na nginx. Brakowało motywacji, bo po pierwsze istniejąca wersja działała, po drugie konfiguracja była lekko zakręcona, po trzecie brak czasu. Ostatecznie któregoś razu zebrałem się i wymyśliłem, że uruchomię oba serwery WWW równolegle. Na różnych portach i zrobię szybki benchmark lighttpd vs nginx. Który to benchmark oczywiście wykaże, że nginx jest szybszy i potwierdzi słuszność przesiadki[1]. 😉

Jak już się zebrałem, to okazało się, że w sumie nie ma aż tak wielu rzeczy skonfigurowanych. A z wielu, które są można czy wręcz wypadałoby zrezygnować. Głównym wyzwaniem okazało się skonfigurowanie nginx tak, żeby HTTP słuchało na niestandardowym porcie i jednocześnie przekierowywało na HTTPS, również na niestandardowym porcie. Znalazłem rozwiązanie, ale machnąłem ręką – dziwne, nieprzystające do normalnego konfiga, a przydatne tylko na moment, przy benchmarku. Za to przydać się może ładny gotowiec do przekierowań z wersji z www na bez www i odwrotnie.

Przy okazji instalacji SSL dowiedziałem się, że w końcu istnieje oficjalna paczka z klientem Certbot dla certyfikatów SSL od Let’s Encrypt w Jessie. Trzeba skorzystać z backportów. Plus, strona daje gotowe instrukcje instalacji dla popularnego oprogramowania (znowu: nginx jest, lighttpd nie ma). Czyli w certyfikatach też został zrobiony porządek. Dla pamięci: znalazłem stronkę z gotowcem, jak uzyskać A+ na popularnym teście SSL. Nieco przestarzała, ale nadal przydatna.

W zasadzie poszło zaskakująco dobrze, najwięcej niespodzianek wyszło na rzeczach najprostszych. A to serwer nie kompresował treści (tu jest o włączaniu kompresji), a to był problem z przetwarzaniem skryptów PHP. W końcu jest sensowna obsługa haseł na dostęp do stron (ew. miałem to wcześniej zrobione słabo).

Z rzeczy, które powinny działać, a nie działają – HTTP/2. Nie wiem, czy bardziej kwestia konfiguracji, wersji nginx, czy Firefoksa, ale wg testu HTTP/2 działało. Za to w Firefoksie (i na niektórych testach, zapewne korzystają z Firefoksa) strona się nie otwierała. Na innych przeglądarkach działało OK, ale do czasu rozwiązania problemu wyłączam HTTP/2. Tak czy inaczej w starciu lighttpd vs nginx wygrał u mnie ten ostatni.

Ponieważ wygląda, że publiczne motywatory działają: następna w kolejce jest przesiadka z chronicle na pelican na Wattmeter. Robi dobre wrażenie i jest w Pythonie. 😉

[1] Na przykładzie strony nextbike.tk i prostego testu przy pomocy ab -n 2000 -c 20 okazało się jednak, że różnicy większej niż błąd pomiaru nie ma. Być może kwestia wielkości małej wielkości pliku i narzutu na transmisję. Abo może może kwestia obciążenia serwera. Konfigi serwerów też nie były ani identyczne, ani optymalizowane. W każdym razie dla mnie szybciej nie będzie.

Drobne zmiany na planecie

Tak jest zawsze. Wszystko może działać od wieków stabilnie, ale jeśli tylko zrobię restart maszynki, mając mało czasu, to wychodzą kwiatki. Tak było i wczoraj z routerem (o tym kiedyś…), tak było i dziś z planetą Joggera. Restart dedyka przed wyjściem do pracy (o dziwo wstał bez problemu), bo już trochę długo działał i kernel stary, a ciągle zapominałem, odpalam stronę w tramwaju w drodze do pracy i… już gdzieś to widziałem.

Okazało się, że skrypt zaciągnął stare wpisy z jednego z feedów[1]. Początkowo podejrzewałem czyszczenie cache planety, który leżał w /tmp albo cache lighttpd (w ramach motywacji: wkrótce przejście na nginx), ale szybko wykluczyłem tę drugą możliwość. Cache planety był w /tmp i z tym nic nie zrobię, bo /tmp jest czyszczony przy restarcie, więc pomyślałem, że trudno i wkrótce się wyrówna.

Ale po powrocie do domu siadłem jednak do debugu. Na oko dziwna struktura feedu, który lądował na początku, ale validatory mówią, że tak może być i generalnie feed poprawny. Jedyne co się rzuca w oczy to lastBuildDate równe z datą pobrania pliku. Nie wiem, czy błąd, czy home made SEO, w każdym razie w połączeniu z brakiem informacji o dacie publikacji poszczególnych postów skutecznie chwilowo popsuło planetę[2].

W ramach mitygacji (nie kalkując z angielskiego: łagodzenia) zrobiłem dwie rzeczy. Po pierwsze, liczba postów na planecie z danego feedu jest ograniczona do trzech. Po drugie (i tego w repo nie będzie), cache wylądował poza /tmp. Czy się sprawdzi? Pożyjemy, zobaczymy. Gdyby ktoś zauważył jakieś problemy z ilością wpisów z feedu – proszę o kontakt.

[1] Dokładnie http://karbownicki.com/rss.xml

[2] Jeśli to możliwe, proszę o poprawienie tej daty.

KVM i task blocked for more than 120 seconds – solved

Sprawę miałem opisać już jakiś czas temu i zapomniałem, a jest szansa, że komuś się przyda. Był sobie serwer, na którym działało trochę VPSów. Wszystkie KVM, wszystkie z systemem plików ext4 i obrazem dysku qcow2. Czyli standard. Sprzęt nie pierwszej młodości, ale działały względnie stabilnie. Poza jedną, w sumie najbardziej obciążoną, bo działał w niej jeden z serwerów Zabbixa. Niespecjalnie obciążony w porównaniu z innymi, w których jednak żaden nie działał w KVM.

Tej jednej zdarzał się zaliczyć zwis, z komunikatami dotyczącymi KVM i task blocked for more than 120 seconds:

kernel: INFO: task XXX blocked for more than 120 seconds.kernel: "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.

Wymagany był reboot wirtualki. Dotyczyło to różnych tasków, a całość działa się losowo. Potrafiło działać przez kilka tygodni, a potrafiło wywalić się co parę dni, co nie ułatwiało diagnostyki. Początkowo działo się to na tyle rzadko, że sprawa została zignorowana. Jedkal w miarę wzrostu obciążenia maszyny fizycznej, problem się nasilał. Objaw był taki, że operacje wymagające zapisu na dysk nie wykonywały się (czyli monitoring zdychał). Zacząłem szukać przyczyn. Pierwotnie podejrzenie padło na coś, co wykonuje się z crona, bo sporo procesów crona wisiało. Jedak przejrzenie skryptów pokazało, że niespecjalnie mogą one być przyczyną

Wyglądało, jakby momentami coś nie wyrabiało się dostępem do dysków w momentach większego obciążenia. Z tym, że znowu – widać było, że nie jest to deterministyczne. Ponieważ maszyny jak wspomniałem starawe, to podejrzenie padło na sprzęt – problemy z dostępem do dysków potrafią robić cuda. SMART pokazywał, że wszystko OK, ale sprawdzić nie zawadzi… Przeniesienie wirtualki na inną, mniej obciążoną maszynę fizyczną nie przyniosło rezultatów – wieszało się nadal, chociaż rzadziej.

Oczywiście wyłączenie komunikatu, które jest w nim wspomniane, nie rozwiązuje problemu. W międzyczasie trafiłem na opis rozwiązania problemu KVM task blocked, czyli zmniejszenie vm.dirty_ratio oraz vm.dirty_backgroud_ratio. Tylko że… to nie pomogło. Nie pomogło także zwiększenie kernel.hung_task_timeout_secs początkowo do 180, potem do 300 sekund. Było trochę lepiej, ale problem nadal występował. Pół żartem, pół serio zacząłem się zastanawiać nad automatycznym rebootem po wystąpieniu problemu (zawsze to krótsza przerwa), ale to brzydkie obejście, nie rozwiązanie. Tym bardziej, że w miarę wzrostu obciążenia i VPSa, i maszyny fizycznej na której on działał, problem zaczął występować częściej. Góra co parę dni. Paradoksalnie, dobrze się stało, bo i motywacja większa, i sprawdzanie efektu wprowadzonych zmian łatwiejsze.

Z braku opisów w sieci, pomocy znajomych adminów i innych pomysłów zacząłem sprawdzać po kolei wszystko. Od fsck systemu plików, przez nowsze wersje kernela, zarówno na maszynie fizycznej, jak i na wirtualce – a nuż coś poprawili. Bez rezultatu. Ostatecznie postanowiłem zmienić format dysku wirtualki z qcow2 na raw i… trafiony, zatopiony – wirtualka zaczęła działać stabilnie.

Dla pewności wróciłem jeszcze z raw z powrotem na qcow2, na wypadek, gdyby chodziło o jakieś błędy, których nie wykrywało narzędzie do sprawdzania qcow2, ale… problem natychmiast wrócił. Gwoli ścisłości: ww. tuning dotyczący parametrów kernela z serii vm.dirty został zachowany.