Kategorie
Administracja publiczna Publicystyka

Czy Profil Zaufany mógłby wytrzymywać nieco większe obciążenia? Prosimy?

Ten artykuł jest inspirowany przez Narodowy Prima Aprilis czyli kolejny przypadek, w którym pięć procent obywateli próbuje jednocześnie skorzystać z rządowych usług online a one przyklękają, przewracają się i umierają. Dzieje się to niestety regularnie. Wrzućcie w Google hasło „profil zaufany nie działa” i zerknijcie na liczbę wyników.

Zastanowimy się dzisiaj, jak to jest, że Facebook, Twitter czy Instagram wytrzymują wizytę dziesiątek lub setek milionów użytkowników dziennie a Profil Zaufany ma problem z obsługą setek… tysięcy. W rozważaniach skupimy się na technologiach webowych, bo puste okno lub komunikat błędu w przeglądarce internetowej to pierwszy zwiastun problemów. Bardzo często jest też tak, że inne kanały dostępu – np. apki mobilne – korzystają z tego samego zaplecza serwerowego, więc awaria odcina użytkowników od e-administracji na dobre.

Jak działa serwer WWW

Serwer jest złożony z takich samych części, jak twój laptop czy komputer stacjonarny stojący pod biurkiem. BZZZZZ, błąd! A już na pewno nieścisłość!

Wiecie co? Ustalmy to sobie na samym początku – prawie do każdego zdania w tej blogonotce można się przyczepić, że zbytnio upraszcza jakiś temat. Jednocześnie każdy akapit opisuje zagadnienia będące tematami całych książek, więc uproszczenia są nieuniknione. Proszę specjalistów o wybaczenie, w zamian tekst pozostanie czytelny dla nie-specjalistów.

Tak więc serwer jest złożony z podobnych części, co twój laptop czy komputer stacjonarny. Procesor może mieć więcej rdzeni i działać z wolniejszym zegarem – dzięki temu jego moc obliczeniową łatwiej będzie podzielić na wiele równoległych zadań. Kości pamięci będą podobne, dyski twarde identyczne. Zdecydowanie różnić się będzie obudowa i zasilacz – serwery umieszcza się w szerokich, płaskich obudowach i przykręca jeden nad drugim w specjalnych szafach.

Tak wygląda komputer w obudowie serwerowej, wysokość 1U (jedna jednostka czyli 45 mm)

Na serwerze instaluje się jakiś system operacyjny (prawie zawsze Linux albo Windows) oraz oprogramowanie realizujące jakieś usługi. Aby nasz sprzęt mógł serwować strony WWW, musimy skonfigurować np. serwer Apache albo nginx i wskazać, gdzie na dysku znajdują się pliki wchodzące w skład strony. Uważni czytelnicy spostrzegli, że słowo „serwer” najpierw oznaczało maszynę a chwilę później program. Znaczenia te nakładają się, w dalszej części będziemy nazywać komputer „maszyną” albo „hostem”. Na przeglądarkę internetową po stronie użytkownika będziemy mówić „klient”, bo w opisie architektury systemów komputerowych właśnie to słowo oznacza program zwracający się do serwera o wykonanie jakiejś usługi.

Gdy serwer WWW jest skonfigurowany i poprawnie uruchomiony, nasłuchuje na połączenia sieciowe przychodzące z szerokiego świata. Użytkownik wpisując odpowiedni adres strony w przeglądarce sprawia, że do serwera wysłany zostaje tekst żądania wyglądający np. tak:

GET / HTTP/2
Host: informatykzakladowy.pl
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate, br

Serwer odczytuje tekst żądania, przygotowuje dla użytkownika zawartość strony i odsyła ją zakodowaną w języku HTML. Przykładowy komunikat zwrotny może zaczynać się następująco:

<!DOCTYPE html>
<html class="no-js" lang="pl-PL">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0" >
    <title>Informatyk Zakładowy -</title>

Ile żądań potrzeba, by wyświetlić jedną stronę?

Ogólnie – im mniej żądań tym szybciej strona się załaduje i narysuje. W typowym przypadku mamy jedno żądanie skutkujące pobraniem pliku HTML z zawartością tekstową, kilka – by pobrać pliki Javacriptu i arkusze styli CSS, do tego po jednym żądaniu na każdy obrazek.

Trzeba wspomnieć o dwóch ważnych mechanizmach przyspieszających ładowanie stron WWW:

  • cache czyli pamięć podręczna. Przeglądarka zapisuje pobrane pliki na dysku, aby przy następnym wejściu na stronę nie ściągać z serwera wszystkich zasobów od nowa. Serwer może na przykład wraz z obrazkiem przekazać informację, że jego zawartość pozostanie niezmienna przez pół roku. Dzięki temu przez wiele miesięcy strona będzie się otwierała nieco szybciej, niż za pierwszym razem.
  • przesyłanie wielu plików przez jedno połączenie sieciowe. Dawniej działo się to sekwencyjnie (plik za plikiem), w czasach protokołu HTTP/2 wysyłane pliki mogą się przeplatać. W ten sposób przeglądarka szybciej dostanie dane pozwalające na rozpoczęcie rysowania strony na ekranie.

Zwróćmy uwagę na to, że w przypadku większości stron WWW serwer zajmuje się danym klientem tylko przez krótką chwilę. Gdy ktoś otwiera stronę, serwer przesyła mu wszystkie pliki (zajmie to sekundę lub dwie) a następnie połączenie zostaje zamknięte. Gdy ów ktoś kliknie link, cały proces pobierania strony i zasobów rozpocznie się od nowa.

Ilu użytkowników może korzystać naraz z jednego serwera

Uwaga, tu liczba uproszczeń będzie poważna.

Domyślne konfiguracje popularnych serwerów WWW przewidują obsługę kilkuset jednoczesnych połączeń. Bez szczególnych problemów możemy zwiększyć tę wartość do tysiąca. Jeśli obsługa jednego odwiedzającego potrwa sekundę, to nasz serwer będzie w stanie obsłużyć ponad trzy i pół miliona odsłon na godzinę (1000 klientów * 60 sekund * 60 minut = 3.600.000 zadowolonych odwiedzających). Całkiem dużo, nie?

Mało znany fakt – nawet Raspberry Pi 3B obsłuży ponad 1000 połączeń na sekundę
obrazek: Wikimedia Commons, Gareth Halfacree, licencja CC BY 2.0

Cóż, w przypadku nowoczesnych usług sytuacja nie wygląda tak dobrze. Weźmy takiego Twittera – jeśli napiszemy jakiegoś tweeta i mamy go na ekranie, widzimy na bieżąco zmiany wartości liczników polubień i odpowiedzi. Gdy używamy Facebooka, na żywo skaczą lajki, znaczniki konwersacji i powiadomień. Oznacza to, że przez większość czasu aktywne jest jakieś połączenie sieciowe między naszym komputerem a infrastrukturą Twittera/Facebooka.

Czas trwania sesji pojedynczego klienta może w takiej sytuacji wydłużyć się z sekund do godzin. Jedna maszyna będzie w stanie obsłużyć kilkanaście-kilkadziesiąt tysięcy użytkowników naraz – tym razem przy użyciu oprogramowania napisanego specjalnie w tym celu. Oznacza to, że kilka milionów jednoczesnych sesji będzie wymagać tysięcy takich maszyn.

Dochodzimy w ten sposób do problemu skalowalności. Musimy znaleźć sposób na to, aby radzić sobie z rosnącą liczbą użytkowników. Oczywiście największe na świecie serwisy online wymagają unikalnych rozwiązań, jednak te mniejsze (czytaj – obsługujące kilka milionów użytkowników dziennie) możemy budować według reguł znanych i sprawdzonych. Oto one.

Skalowanie pionowe i poziome

Typowa strona WWW należąca do zakładu szewskiego, hurtowni dewocjonaliów czy stowarzyszenia hodowców turkucia podjadka, odnotuje dziennie kilkadziesiąt lub kilkaset odsłon – obciążenie CPU hosta będzie skrajnie małe. To sprawia, że firmy hostingowe są w stanie zaoferować ceny rzędu kilkunastu złotych miesięcznie, po prostu ładują setki małych serwisów na jedną maszynę i wszyscy są zadowoleni. Informatyk Zakładowy działa na takim właśnie dzielonym hostingu w Dreamhoście (a jeśli planujesz kupić tam usługi, skorzystaj z tego linka, dzięki!).

Cztery procesory Intel® Xeon®, 96 slotów na RAM (do 6 TB), 24 zatoki na HDD. Nie jest tanio.

Oczko wyżej w hierarchii hostingów są maszyny wirtualne (virtual machine, VM), czyli od kilku do kilkudziesięciu hostów „symulowanych” na jednym fizycznym komputerze mającym silny procesor i dużo pamięci. Przewagą tej opcji jest gwarantowany przydział RAM-u i mocy obliczeniowej oraz większa prywatność – maszyna wirtualna jest przydzielona tylko jednemu nabywcy. Jeśli ktoś potrzebuje mocy bez żadnych kompromisów, mamy jeszcze tzw. „goły metal” czyli maszyny wynajmowane na wyłączność.

Co możemy zrobić, jeśli liczba odwiedzających stronę rośnie a nasz serwer WWW zaczyna zwalniać? Pierwszym pomysłem jest zawsze „więcej” czyli więcej RAM-u, wydajniejszy CPU, szybsze dyski. Jest to tak zwane skalowanie pionowe i działa aż do momentu, w którym nie da się już ulepszać pojedynczego komputera (odporność pojedynczego węzła na awarie to temat na zupełnie inną opowieść).

Gdy popularność serwisu nadal rośnie, musimy przejść na skalowanie poziome, czyli zastosować konfigurację w której będziemy mieli wiele hostów serwujących jedną stronę WWW (tutaj słaby dowcip o tym, że przy skalowaniu poziomym komputery mogą być przykręcone w szafie jeden nad drugim, haha). Od strony internetu wystawimy tzw. load balancer czyli usługę rozkładającą ruch przychodzący na wszystkie dostępne maszyny, stosownie do ich obciążenia w danym momencie.

Komputery i urządzenia sieciowe szafach rackowych
źródło: Wikimedia Commons, Alexis Lê-Quôc, licencja CC BY-SA 2.0

Rozłożenie ruchu na pięć czy piętnaście komputerów nie wydaje się szczególnie trudne, gdzie tkwi haczyk?

Dynamiczna zawartość i bazy danych

Protokół HTTP, służący do komunikacji między przeglądarką a serwerem WWW, jest bezstanowy. Oznacza to, że każde żądanie trafiające do serwera jest autonomiczne i może być przetwarzane w izolacji od pozostałych. To bardzo ułatwia skalowanie wydajności serwisu metodą dorzucania do puli kolejnych maszyn.

Serwer WWW nie jest jednak jedynym komponentem, o którego skalowanie musimy się zatroszczyć. Po stronie serwerowej większości witryn znajdziemy prawie zawsze drugą z podstawowych usług – serwer bazodanowy. Tu o skalowanie jest niestety trudniej.

Czasem zamiast 8 procesorów po 8 rdzeni potrzebujesz jednego procesora mającego 64 rdzenie. Na przykład do serwera bazodanowego. (x-kom)

Relacyjne bazy danych bardzo dobrze nadają się do przechowywania informacji o związkach między osobami i rzeczami. Przykładem może być sklep internetowy – mamy w nim konta klientów, klienci mają adresy, asortyment ma stany magazynowe, zamówienia wiążą klienta z asortymentem, faktury wiążą się z zamówieniami, płatności z fakturami i tak dalej.

Dzięki informacjom zgromadzonym w bazie danych, wiele witryn jest w stanie generować zawartość strony dynamicznie, na żądanie, zależnie od tego, kto ją odwiedza. Przykład – sklep internetowy i podstrona „Moje zamówienia”, gdzie każdy klient widzi wyłącznie swoje zamówienia.

Wyświetlenie tej podstrony może mieć następujący przebieg:

  1. Serwer otrzymuje żądanie wyświetlenia strony z zamówieniami, w ciasteczku dołączony jest identyfikator sesji
  2. Serwer odpytuje bazę danych, czy taka sesja istnieje i jest ważna
  3. Jeśli tak, serwer odpytuje bazę danych o kwoty i daty 20 najnowszych zamówień
  4. Serwer dostaje listę zamówień, wstawia nazwy i daty zamówień w tabelkę w szablonie strony WWW
  5. Serwer odsyła klientowi treść strony WWW

Często na potrzeby wyświetlenia jednej strony baza danych przetworzy kilkadziesiąt zapytań. Choć są to operacje bardzo szybkie i jeden serwer bazodanowy może obsłużyć wiele serwerów stron WWW, to kiedyś i on osiągnie granice swych możliwości. Co wtedy?

Skalowanie baz danych

Od relacyjnych baz danych oczekujemy spójności czyli natychmiastowego odzwierciedlenia wszystkich zmian. Ktoś kupił ostatni egzemplarz książki? Nie możemy dopuścić, aby nabył ją ktokolwiek inny. Z tego powodu podział jednej wielkiej bazy na dwie czy trzy mniejsze jest w zasadzie niemożliwy – chyba, że podzielimy serwis na części niezależne od siebie. Spójrzmy na internetowy sklep Amazona. Choć konto w tym serwisie działa we wszystkich witrynach „narodowych”, to jednak Amazon na rynkach amerykańskim, brytyjskim, francuskim czy włoskim ma odrębny asortyment i stany magazynowe.

W skalowaniu dostępności relacyjnej bazy danych pomoże nam funkcja replikacji. Jeden bazodanowy przyjmuje wszystkie żądania zapisu (utworzenie zamówienia, zdjęcie towaru ze stanu itd.) a informację o przeprowadzonej operacji rozsyła do replik – osobnych maszyn dających dostęp „tylko do odczytu”. Serwery WWW mogą przesyłać żądania odczytu danych do którejkolwiek repliki, dzięki czemu wydajność serwera bazodanowego zostaje zwielokrotniona.

W niektórych zastosowaniach możemy nieco poluzować wymogi dotyczące spójności danych. Wówczas będziemy mogli dopuścić zapis danych w wielu węzłach – kosztem opóźnień w synchronizacji. Przykład: licznik osób obserwujących nasz profil na Twitterze prezentuje informację, od której praktycznie nic nie zależy. Nie musimy dbać o to, by wskazanie było aktualne co do sekundy, minuta opóźnienia nie robi różnicy. Sytuację taką możemy zaobserwować, odświeżając np. licznik lajków. Gdy ich liczba skacze w górę i w dół, jest to sygnałem, że zapytania są obsługiwane przez różne węzły, które nie uzgodniły jeszcze wspólnej listy lajkujących (tzw. eventual consistency).

Metody na poprawienie wydajności witryn

Nawet, gdy nasz serwer serwuje zawartość generowaną dynamicznie, nadal duża część zasobów jest statyczna – zdjęcia, arkusze CSS, pliki z Javascriptem i tak dalej. Dobrym pomysłem jest wydzielenie zasobów statycznych i umieszczenie na osobnym zestawie maszyn, dostępnych pod inną domeną lub subdomeną.

Będziemy wówczas w stanie zoptymalizować wykorzystanie naszych zasobów sprzętowych. Zestaw maszyn odpowiedzialnych za zawartość statyczną może być mieć słabsze procesory i wolniejsze dyski – tu nie będziemy przetwarzać żadnych danych. Lepiej wyposażone urządzenia będą mogły całą moc przeznaczyć na generowanie zawartości dynamicznej i tylko one będą komunikować się z bazą danych.

Do tej pory milcząco zakładaliśmy, że zawartość dynamiczna będzie przygotowana po stronie serwera, że to serwer skonstruuje wynikowy HTML do wyświetlenia w przeglądarce. Nie musi tak być, od dawna w użyciu są języki i frameworki budujące finalną zawartość strony po stronie klienta.

Przykładowy szablon pobierany (i trzymany w cache) przez przeglądarkę może wyglądać następująco:

Witaj {{imie}}, masz {{licznik_nowych_wiadomosci}} nowych wiadomości.

Treść nie jest oczywiście wyświetlana w takiej postaci, potrzebny jest jeszcze wynik osobnego żądania zwracającego następującą strukturę danych:

{
  "imie": "Tomek",
  "licznik_nowych_wiadomosci": 15
}

Takie dane w formacie JSON mogą pochodzić bezpośrednio z bazy danych, wtedy zadaniem serwera WWW będzie jedynie uwierzytelnianie użytkownika i pośrednictwo w komunikacji z bazą. Oznacza to, że serwer zużyje mniej czasu i zasobów (CPU, RAM) na przetworzenie takiego żądania, więc będzie w stanie obsłużyć więcej użytkowników w jednostce czasu.

Dalsze metody na poprawienie wydajności

Zauważmy, że „wydajność” jest tu pojęciem bardzo nieostrym, w naszych rozważaniach na zmianę gonimy za „taniej” (mniejszy koszt utrzymania strony) i „lepiej” (lepsza obsługa użytkowników wchodzących na stronę).

Niekiedy jednym ruchem uda nam się poprawić wskazania na obu osiach – będzie tak, gdy zdecydujemy się na użycie tzw. Content Delivery Network. Jest to usługa polegająca na obsłużeniu części zapytań do naszej strony przez sieć maszyn rozproszonych po całym świecie. Pierwsza korzyść – te zapytania zostaną zrealizowane znacznie szybciej, bo CDN jest wpięty w liczne łącza międzyoperatorskie i tam każdy ma blisko. Druga korzyść – zapytania te nie obciążają naszych serwerów, co obniża nam koszty.

Przykładem korzyści płynących z użycia CDN-a jest Informatyk Zakładowy. W sierpniu 2020 opublikowałem tekst „Fotografia obliczeniowa”, który zawierał dziesiątki ilustracji ważących setki kilobajtów każda oraz ściągnął największą jak dotąd falę odwiedzających (ponad 800 osób jednocześnie na stronie). Dzięki temu, że skorzystałem z darmowej usługi CDN-a Cloudflare, blog na zwykłym dzielonym serwerze utrzymał to obciążenie. Przez tamten miesiąc odwiedzający Zakładowego pobrali łącznie ponad terabajt danych, z czego 97% wysłał im Cloudflare.

Cennik na stronie Cloudflare, CDN dostępny w gratisie

Typową metodą obniżenia kosztów i przyspieszenia pracy serwisu WWW jest użycie serwerowych mechanizmów typu „cache”, które przechowują wynik pracochłonnych obliczeń i serwują go przez pewien czas. Osiągane korzyści okupione są określoną ceną – zazwyczaj cache serwuje dane lekko nieaktualne albo różne grupy użytkowników otrzymują różne odpowiedzi na to samo pytanie. Zawsze będzie coś za coś – gdy np. spróbujemy zredukować negatywny wpływ poprzez kierowanie jednej grupy użytkowników zawsze do tej samej grupy serwerów ze wspólnym cache, wzrośnie poziom komplikacji load balancerów. Nie będą one mogły – jak dotąd – w prosty sposób przekierować żądania do najmniej obciążonego hosta. Zamiast tego konieczny będzie wgląd w przesyłane dane i podjęcie decyzji na bazie odczytanych informacji.

Sezonowe różnice obciążenia

Większość opisanych wyżej technik optymalizacji jest w użyciu od dwudziestu lat. Już wtedy stosowano skalowanie poziome i pionowe, podział na zasoby statyczne i dynamiczne, rozpraszanie geograficzne i tak dalej. Skąd więc ciągła pogoń za kolejnymi metodami skalowania? Odpowiedź jest prosta – sezonowe różnice obciążenia.

W przeszłości każdy dostawca usług online musiał wyposażyć swoją serwerownię w tyle maszyn, by udźwignąć maksymalne spodziewane obciążenie (plus szacowany margines bezpieczeństwa). W świecie e-commerce oznaczało to planowanie całej infrastruktury na 2-3 tygodnie poprzedzające Boże Narodzenie – przez pozostałą część roku połowę maszyn można byłoby na dobrą sprawę wyłączyć. Jeśli zaś świąteczny ruch przekroczył oczekiwania, firma traciła potencjalne zyski nie mogąc obsłużyć wszystkich chętnych.

Wybory Prezydenta Rzeczypospolitej Polskiej mają miejsce co 5 lat

Skrajnym przykładem różnic sezonowych będzie witryna Państwowej Komisji Wyborczej. Przez kilka dni po wyborach prezydenckich lub parlamentarnych ruch rośnie tam nie dwu- albo trzykrotnie, lecz tysiąckrotnie. Co zrobić? Wydać fortunę, by udźwignąć wielkie obciążenie przez tydzień raz na kilka lat? To pytanie prowadzi nas do nowości sprzed lat dziesięciu.

Usługi chmurowe

Gwałtowna eksplozja popularności usług chmurowych, oferowanych m.in. pod markami Amazon AWS, Microsoft Azure, Google Cloud czy Heroku, nie budzi żadnego zdziwienia. W przeszłości na nowy sprzęt do serwerowni trzeba było czekać tygodnie a umowy kolokacyjne były podpisywane na kwartały lub lata. W chmurze kolejne maszyny wynajmiemy szybciej, niż potrwa zaparzenie herbaty a zapłacimy tylko za rzeczywisty czas ich pracy i to z sekundową dokładnością. Mechanizmy automatycznego skalowania pozwolą dokładać i redukować moc obliczeniową stosownie do bieżącego zapotrzebowania.

Startupy dostały dzięki temu możliwości, jakich nie było nigdy wcześniej. Przypomnijmy sobie przypadek Naszej Klasy – nagła eksplozja popularności serwisu sprawiła, że jego twórcy najpierw musieli znaleźć inwestorów, potem nie nadążali z zakupem i stawianiem nowych maszyn. Obciążenie tygodniami przekraczało możliwości serwerów. Z drugiej zaś strony w tym samym okresie czytaliśmy wywiad z Rafałem Agnieszczakiem, który opowiadał o rozwijaniu serwisu fotka.pl w oparciu o usługi Amazona.

Rozwój usług chmurowych nie zwalnia, dziś mamy do dyspozycji np. środowiska serverless, które… eliminują konieczność zajmowania się jakimikolwiek wynajmowanymi maszynami. Odpowiednio przygotowane oprogramowanie będzie działać na serwerach zarządzanych przez operatora chmury, płynnie przechodząc od zera do miliona użytkowników (lub odwrotnie) – operator usługi zapłaci tylko za zużyty czas procesora i zajętą pamięć.

Przy okazji – ktoś mógłby zastanowić się, co AWS robi z dziesiątkami tysięcy serwerów, które w danej chwili czekają na wynajęcie. Cóż, mamy kapitalizm, żadne dobro się nie zmarnuje. Normalne instancje maszyn wirtualnych kosztują kwoty zależne od konfiguracji (taniej przy wynajęciu na rok lub trzy lata). Jeśli mamy do realizacji zadanie, które trzeba zrobić jak najtaniej ale niekoniecznie szybko, wówczas ze zniżkami sięgającymi 90% możemy dostać instancje typu Spot. Jedyny minus – będą one znikać z naszej puli w losowym momencie czyli wtedy, gdy znajdzie się chętny na zapłacenie pełnej ceny.

Co dzieje się, gdy ruch na stronie jest za duży

Serwer WWW czeka na połączenia ze świata na porcie 80 (protokół HTTP) oraz 443 (protokół HTTPS). Gdy użytkownik wpisze adres naszej strony, przeglądarka nawiązuje połączenie TCP/IP z serwerem i wysyła do świeżo utworzonego kanału komunikacyjnego tekst żądania.

Serwer akceptując nowe połączenie przydziela je do konkretnego wątku lub procesu roboczego i wraca do nasłuchu. W prostym przypadku przetwarzanie żądania sprowadzi się do wygenerowania nagłówków odpowiedzi HTTP i odesłania zawartości jakiegoś pliku. W bardziej złożonym przypadku wątek serwera uruchomi np. interpreter języka PHP, przekaże mu otrzymane żądanie i będzie czekał na odpowiedź do odesłania. Jeśli przygotowanie odpowiedzi zależy od zewnętrznych systemów (np. od bazy danych), interpreter PHP może zamilknąć na kilkanaście lub kilkadziesiąt sekund. Albo i dłużej. Przez cały ten czas jeden z wątków roboczych serwera WWW będzie zablokowany.

Przy rosnącym ruchu nastąpi moment, w którym serwer zaakceptuje połączenie i nie będzie ani jednego wątku/procesu roboczego, który mógłby je przyjąć. Takie połączenie trafi wówczas do kolejki połączeń oczekujących i będzie czekać. I czekać. Po 20-30 sekundach gapienia się na biały ekran użytkownik kliknie guzik „Odśwież”. Dla pewności kilka razy. Wiecie, co się stanie? Tak, do kolejki połączeń oczekujących trafi następnych kilka połączeń.

Z sieciami TCP/IP jest bowiem tak, że często jedyną metodą sprawdzenia, czy połączenie jeszcze żyje, jest próba wysłania czegoś. Gdy ktoś klika „Odśwież”, jego poprzednie połączenie zostaje zamknięte po stronie przeglądarki, ale nie ma pewności, że pakiet z informacją o terminacji dotrze do serwera. Przeglądarka po 300 sekundach sama się zresztą podda i przestanie czekać (użytkownicy zobaczą wówczas komunikat „przekroczono limit czasu połącznia” lub podobny). Serwer o obu tych sytuacjach dowie się dopiero wtedy, gdy napracuje się przygotowując odpowiedź a przy próbie jej wysłania dostanie informację „sorry, za późno, ten klient już sobie poszedł”.

Mamy więc sytuację, gdy użytkownicy klikają „Odśwież”, coraz więcej połączeń czeka w kolejce, wszystkie wątki robocze robią co mogą ale z powodu opóźnień coraz mniej danych trafia na czas do przeglądarek.

Ruch rośnie nadal, co wtedy?

Kolejka połączeń oczekujących na obsłużenie ma skończony rozmiar. Gdy zostanie on osiągnięty, kolejne połączenia przychodzące będą natychmiast odrzucane a użytkownik zobaczy w przeglądarce komunikat „Serwer odrzucił połączenie”. Dzięki temu obciążenie serwera WWW przestaje rosnąć. Co jednak robi użytkownik? Oczywiście natychmiast klika „Odśwież”, dla pewności kilka razy.

Kolejnym zagrożeniem stanie się limit jednoczesnych połączeń obsługiwanych przez urządzenia sieciowe. Każde połączenie TCP/IP jest jednoznacznie identyfikowane przez cztery liczby: numer IP klienta, numer IP serwera oraz numery portów po obu stronach. Zwykły router przepycha pakiety patrząc jedynie na docelowy adres IP. Jeśli jednak korzystamy z jakiegoś load balancera rozkładającego ruch na wiele maszyn, musi on pamiętać które połączenie było przekierowane do którego hosta (jedno żądanie podróżuje w wielu pakietach, wszystkie muszą trafić pod jeden adres).

Limity są w takich urządzeniach bardzo wysokie – idą w setki tysięcy lub nawet miliony połączeń. Co stanie się, gdy i te wartości zostaną przekroczone? Po stronie klienta niewiele – miks połączeń odrzuconych i przeterminowanych. Niespodzianka czeka za to administratora serwisu – od tego momentu także on nie będzie miał łączności ze swoim sprzętem. Jeśli ktoś może podejść do maszyny i zalogować się na konsoli, ma szansę w ten czy inny sposób ogarnąć sytuację. Jeśli serwerownia jest w innym mieście, cóż – może przed następnym kryzysem uda się przygotować awaryjne łącze, przez które nie będzie przechodził ruch generowany przez użytkowników końcowych.

Co można zrobić, aby to wszystko nie zatykało się na amen?

Rozwiązanie jest bardzo proste – zanim nasz system przewróci się pod rosnącym obciążeniem, należy zaniechać bezowocnej próby realizacji usługi i poinformować użytkownika, że jego żądanie odrzucono. U początków Naszej Klasy często trafialiśmy na Pana Gąbkę czyli statyczny obrazek informujący o przeciążeniu. Użytkownicy nadal byli sfrustrowani, ale daleko mniej, niż przy niekontrolowanym załamaniu pracy serwisu.

Twórcy niektórych usług idą krok dalej i przy rosnącym obciążeniu wyłączają część funkcji lub obniżają standard obsługi. Można to zaobserwować np. w Arkuszach Google i jednoczesnej edycji jednego arkusza przez setkę lub więcej użytkowników. Prawa do modyfikacji zawartości będą przydzielone pierwszym kilkudziesięciu osobom, pozostałe będą miały dostęp tylko odczytu.

Czasem poziom dostępności usługi będzie wprost powiązany z planem abonamentowym. Usługa GeForce NOW, pozwalająca na uruchamianie w chmurze gier komputerowych, dostępna jest w wariancie darmowym i płatnym. Użytkownicy komercyjni mają priorytetowy wjazd na serwery, w wariancie darmowym chętni ustawiają się w długie kolejki i czekają na dostęp do wolnego slotu.

Jak działa Profil Zaufany i dlaczego wszystko od niego zależy

Jako obywatele chcemy mieć możliwość korzystania z usług administracji publicznej – używać Internetowego Konta Pacjenta, sprawdzać punkty karne czy zarządzać danymi firmy w centralnej ewidencji działalności gospodarczej.

Wszystkie te serwisy korzystają ze scentralizowanego, państwowego systemu login.gov.pl spinającego usługi z dostawcami tożsamości. Ten ostatni termin określa systemy przechowujące informacje o użytkownikach końcowych, które to informacje – za zgodą użytkowników – można przekazywać dostawcom usług. Korzyści są oczywiste – obywatele nie muszą zakładać kont w każdym kolejnym serwisie, mają też jeden uniwersalny sposób logowania, który łatwiej zabezpieczyć niż wiele odrębnych. Są też i wady – jeśli z powodu nagłego szturmu na szczepienia system login.gov.pl padnie, problem mają użytkownicy pozostałych usług administracji publicznej.

Jak wygląda typowa sekwencja logowania do jakiejś Usługi z wykorzystaniem Dostawcy Tożsamości? Mniej więcej tak:

UżytkownikUsługaDostawca Tożsamości
hej Usługo, chcę się zalogować
rozmawiaj z Dostawcą Tożsamości, powołaj się na mnie
hej Dostawco Tożsamości, chcę się zalogować do Usługi, oto mój login i hasło
nazwa i hasło się zgadzają, oto twój token Użytkowniku, pokaż go Usłudze
hej Usługo, chcę się zalogować, oto mój token
Dostawco Tożsamości, dostałam od Użytkownika taki token, jest w porzo?
tak, Usługo, to token Jana Kowalskiego, PESEL xxxxx, telefon yyyyyy
ekstra, wiem już z kim mam do czynienia, witam Użytkowniku Kowalski
no elo

Teraz uwaga. Po pierwsze – ta tabelka powyżej zawiera poważne uproszczenia. Jeśli ktoś chce poznać prawdziwe diagramy przepływów, zapraszam do lektury dokumentacji Węzła Krajowego. Po drugie – jakiego znowu Węzła?

Ano, niestety. Dawniej było prosto – na stronie WWW portalu ePUAP zakładaliśmy konto z hasłem, szliśmy do urzędu potwierdzić że my to my, wychodziliśmy z potwierdzonym kontem. Potem udostępniono możliwość logowania za pośrednictwem systemów bankowych (już bez odwiedzin w urzędzie), bo skoro banki weryfikowały tożsamość swoich klientów, to równie dobrze mogą ją potwierdzić na potrzeby usług online.

Terminologia związana z Profilem Zaufanym mocno się w ostatnich latach skomplikowała, alternatywnym dostawcą tożsamości został system e-dowód oparty na dowodach osobistych z chipem (i podpisem cyfrowym realizowanym przez apkę mobilną eDo App albo czytnik podłączany do peceta). Kilka banków weszło też w alians z Krajową Izbą Rozliczeniową, która przygotowała środek identyfikacji elektronicznej o nazwie mojeID. Węzeł Krajowy Identyfikacji Elektronicznej (to, co użytkownicy widzą pod adresem login.gov.pl) jest więc elementem spinającym wiele alternatywnych dostawców tożsamości z dostawcami usług online.

Czy ktoś z szanownych Czytelników jeszcze nadąża za tematem? Nie? Zero zdziwienia – to wszystko jest diablo skomplikowane a samokształcenie utrudnia fakt, że na te same rzeczy mówiono kiedyś inaczej (pamięta ktoś markę eGO?). Aby w poprzednich dwóch akapitach nie nakłamać, spędziłem dobrą godzinę na czytaniu różnych dokumentów z ostatniej dekady, doktoryzowaniu się z eIDAS-a i dopytywaniu mądrzejszych ode mnie czy na pewno dobrze to wszystko zrozumiałem. A przecież siedzę w branży IT od dwóch dekad!

Czy to całe rządowe logowanie mogłoby działać lepiej?

Wielkim łukiem wróciliśmy do początkowego pytania – co zrobić, aby logowanie z użyciem Profilu Zaufanego wytrzymywało większą liczbę chętnych? Kilka dni temu dowiedzieliśmy się, o jakich obciążeniach mowa – Michał Dworczyk powiedział: „O ile normalnie w ciągu sekundy mamy od 5 do 10 prób zalogowania na Profilu Zaufanym, tak dzisiaj mamy tych prób około pół tysiąca”.

500 prób logowania na sekundę to dużo czy mało? Porównania do największych serwisów online są nie fair, ale pozwolą nam określić, co jest a co nie jest możliwe. Otóż: standardowe obciążenie Whatsappa to 500 tysięcy wiadomości na sekundę. Twitter obsługuje miliony zalogowanych użytkowników i pięć tysięcy twitów na sekundę, ale w szczycie jest w stanie wytrzymać 143 tysiące twitnięć. Facebook przyjmuje co sekundę kilka tysięcy zdjęć i kilkadziesiąt tysięcy lajków.

Mówiąc krótko – istniejące systemy informatyczne wytrzymują obciążenia większe o 2-3 rzędy wielkości. Zdaję sobie oczywiście sprawę z tego, że administracja publiczna obciążona jest koniecznością integrowania wielu niekoniecznie najnowszych systemów, jednak stan bieżący jest nie do zaakceptowania. Profili zaufanych mamy dziewięć milionów. Średnie tempo 5-10 logowań na sekundę oznacza logowanie każdego z posiadaczy raz na zaledwie 10-20 dni.

Dodatkowy problem to brak priorytetyzacji wybranych usług lub podatność użytych technik na awarie. 1 kwietnia cytowane 500 prób logowania na sekundę skutkowało niedostępnością nie tylko Portalu Pacjenta, ale także aplikacji gabinet.gov.pl służącej do zarządzania receptami, skierowaniami i ewidencją szczepień, zapewne nieprzypadkowo położyła się też webowa aplikacja do spisu powszechnego.

Serwis login.gov.pl powinien zostać poddany następującym zmianom:

  • każdy z najważniejszych serwisów usługowych (jak Portal Pacjenta, gabinet.gov.pl, CEIDG czy CEPIK) ma mieć wydzieloną, gwarantowaną dla siebie część przepływności serwisu; pozostała część ma stanowić pulę wspólną
  • funkcje realizowane po uwierzytelnieniu użytkownika (czyli odpowiedź na pytania serwisów usługowych) powinny mieć priorytet nad próbami logowania, w przeciwnym razie nakłady poniesione na uwierzytelnienie zostaną zmarnowane – docelowa strona nie zadziała a użytkownik ponowi próbę logowania
  • gdy serwis zbliża się do rzeczywistej granicy wydajności, powinien przekierować użytkownika do zewnętrznej, statycznej strony z informacją o braku możliwości zalogowania

Ponad wszystko jednak – trzeba eliminować kolejne wąskie gardła, optymalizować konfiguracje i dostawiać kolejne maszyny. Skoro pandemia wypromowała usługi online, rządzący muszą zapewnić ich dostępność. Pięćset logowań na sekundę wkrótce będzie normą, login.gov.pl musi wytrzymywać sto razy tyle.

Czy to wystarczy?

Och. W powyższym przydługim wywodzie ani słowa nie poświęciliśmy intencjonalnym atakom DDoS. Na razie nie ma co o tym myśleć, bo system załamuje się pod zwiększonym zainteresowaniem uprawnionych użytkowników, ale temat z pewnością powróci. Im bardziej gospodarka i społeczeństwo będą zależne od usług elektronicznych, tym większym zagrożeniem będzie atak skutkujący ich niedostępnością.

Ostatni obrazek w tekście, budujący atmosferę niepewności i zagrożenia hackerstwem, epatujący cyfrowym upadkiem, wojnami nomadów na rubieżach i promujący noszenie wygodnych bluz z kapturem

W chwilach kryzysu często słyszy się, że nad problemem pracują nasi najlepsi ludzie. Wskutek niezbyt wysokich pensji administracja państwowa ma jednak dostęp do mocno ograniczonej puli talentów z rynku IT. Czasem naprawdę dobrze byłoby zastanowić się, kto bardziej przyczyni się do przyszłych sukcesów naszego kraju – górnik kopalni węgla brunatnego czy specjalista pracujący nad niezawodnością powszechnych usług elektronicznych.

I z tym pytaniem Was zostawiam.



O autorze: zawodowy programista od 2003 roku, pasjonat bezpieczeństwa informatycznego. Rozwijał systemy finansowe dla NBP, tworzył i weryfikował zabezpieczenia bankowych aplikacji mobilnych, brał udział w pracach nad grą Angry Birds i wyszukiwarką internetową Microsoft Bing.

17 odpowiedzi na “Czy Profil Zaufany mógłby wytrzymywać nieco większe obciążenia? Prosimy?”

Tyle że ZUCH/WIIP ciągle jakoś wypłynąć na szerokie wody. Sama koncepcja jest super, tyle że są problemy z realizacją.
PS. Niżej podpisany był jednym z członków zespołu rozwijającego ZUCH/WIIP.

Super artykuł 😀
Na pewno na dobrym poziomie szczegółów dla wielu ludzi, są czasami linki do poszerzenia zagadnienia, bomba!
Tylko mała literówka się wdarła jeszcze:
„to jest a co nie jest możliwe” -> „co jest a co nie jest możliwe”

Mam jakies dziwne przekonanie, ze gdyby Anna Streżyńska pozostala na swoim stanowisku, to szlo by ku lepszemu. A tak jest jak jest.

„Po 20-30 sekundach gapienia się na biały ekran użytkownik kliknie guzik „Odśwież”. Dla pewności kilka razy.”

Że też nie ma mechanizmu, który wiąże klienta z żądaniem i w takiej sytuacji rzuca komunikat: „Przestań! Jeszcze nie skończyłem, a Ty znowu każesz mi robić to samo od nowa.”

Albo nawet klient i serwer mogłyby się porozumieć między sobą, że będą ignorować kolejne próby odświeżania, ale użytkownikowi nie będą o tym mówić. Człowiek by sobie wciskał Odśwież, a bezduszna maszyna nic by sobie z tego nie robiła. Fajnie by było.

Tak ładnie opisałeś o skalowaniu pionowym i poziomym, ale tutaj nasi rządowi informatycy wraz z decydentami powinni się wykazać odrobiną inteligencji. Otóż po co udostępniać możliwość szczepień jednego dnia wszystkim zainteresowanym? Nawet jeśli profil zaufany jest w stanie przetworzyć milion logowań na sekundę to i tak wąskim gardłem jest ilość pielęgniarek, które nas szczepią. Wystarczyłoby każdego dnia (albo co drugi dzień) „uwolnić” jeden rocznik. Wtedy owy ruch rozłożyłby się na 20(40) dni. Dodatkowo niefortunna data 1-go kwietnia nałożyła się ze startem samo-spisu, co też zwiększyło obciążenie rządowych serwerów. No, ale jak w naszym rządzie nie ma odpowiednich osób na odpowiednich stanowiskach, to jest jak jest.

Artykuł świetny.

@Damian Daszkiewicz
Chcesz powiedzieć, że osoba powiedzmy z roku 1970 mogłaby się zalogowac do systemu wyłącznie np. 15 kwietnia, dzięki temu ruch się rozłoży ? 😕

Tylko, że Profil Zaufany nie służy tylko do szczepień, brak pielęgniarek nie jest uzasadnieniem tylko dla fuszerki a sami użytkownicy mogliby być zainteresowani informację kiedy mniej więcej można próbować ponownie. Logiku….

Autor jest bezczelnie skrupulatny i kompetentny dlatego też jego opinia zostanie celowo pominięta przez rządzących którzy jednak mają swoją własną wizję i swój świat. Jedna uwaga, dodanie do nazwy usługi słowa NARODOWY zwiększa prestiż 1000 razy a wydajność drugie tyle, autor chyba o tym nie wie bo nie wspomniał.

Prozaiczna sprawa: nikt nie zdefiniował i nawet nie przymierzył się do wymagań wydajnościowych, a dostawca z własnej inicjatywy i budżetu nie zrobi, nawet jak ma wiedzę. 500 równoległych sesji to jest ŻART – w dobrze napisanym systemie w Javie, na środowisku developerskim z Oracle XE (ten mały darmowy na 1 CPU) to zwykły biurowy laptop Dell ciągnął 200-300 i to z symulatorem ruchu na tej samej maszynie 😀 Tylko bazka się wypełniła. Przy dobrym projekcie i sensownej implementacji, typowy dzisiejszy serwer Della, nawet 1U to pewnie 1-2 tysiące uciągnie nosem, szczególnie że doszły dyski NVMe… 5 użytkowników równolegle na codzień, to świadczy raczej o tym, że ten cały system jest zwyczajnie niepotrzebny.

Polecam na otrzeźwienie – warto uwzględnić DATĘ https://www.salon24.pl/u/rzecznikzus/134601,petru-rozmija-sie-z-faktami

A jak ktoś nie umie projektować i pisać po prostu poprawnego (nie mówię superzoptymalizowanego, poprawnego kodu …)

Ja powiem tyle.. Jak szef nie kazał to co może nawet dobry informatyk? A dyrektor przecież niezapyta bo on wie lepiej.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *