Zakres utrzymania dedykowanych aplikacji webowych

Po odbiorze projektu aplikacja przechodzi z wytwarzania do eksploatacji. Kod jest gotowy w uzgodnionym zakresie, ale środowisko wokół niego stale się zmienia: system operacyjny dostaje poprawki, certyfikaty wygasają, tabele rosną, a użytkownicy zgłaszają błędy i nowe potrzeby. Utrzymanie dedykowanych aplikacji webowych obejmuje więc dwa nurty. Pierwszy to nadzór, który sprawdza, czy program działa. Drugi to zmiany: poprawki błędów i rozwój funkcji.

Dedykowana aplikacja nie ma społeczności użytkowników ani producenta, który rozsyła łatki wszystkim klientom. Wiedza o jej kodzie i konfiguracji skupia się u wykonawcy oraz u zespołu zamawiającego, dlatego obsługę IT trzeba ustalić na etapie umowy, a nie po pierwszej awarii. Podobny podział opisuje artykuł o oprogramowaniu na zamówienie i obsłudze IT.

Rodzaj pracyPrzykładKto ją inicjuje
Incydentaplikacja nie odpowiada, zapis kończy się błędemużytkownik lub monitoring
Problemspowolnienie powtarzające się o tej samej porzeanaliza kilku incydentów
Zmiana drobnanowa kolumna w raporcie, korekta uprawnieniaużytkownik lub kierownik
Rozwójnowy moduł albo integracja z kolejnym systememzamawiający
Zadanie zaplanowaneodnowienie certyfikatu, test odtworzenia kopiiwykonawca według harmonogramu

Reguła: incydent przywraca działanie, a problem usuwa przyczynę - to dwa osobne zgłoszenia, bo mają inny priorytet i inny sposób rozliczenia.

Podział odpowiedzialności

Umowa powinna wskazywać, co należy do wykonawcy, a co do zamawiającego. Wykonawca odpowiada zwykle za kod i migracje bazy. Serwery oraz sieć pozostają po stronie działu IT klienta albo zewnętrznej firmy infrastrukturalnej, na przykład w ramach usługi obsługi Windows Server. Granicę warto opisać na przykładach, bo zgłoszenie „program wolno działa” może dotyczyć zapytania w bazie, przeciążonego serwera albo łącza.

Ten sam podział obowiązuje, gdy aplikacja działa w chmurze. Model, w którym dostawca prowadzi infrastrukturę, przenosi część zadań na jego stronę, ale nie zdejmuje odpowiedzialności za dane i uprawnienia użytkowników. Różnice omawia artykuł o wykorzystaniu chmury obliczeniowej.

Konta i uprawnienia użytkowników

Do stałych zadań utrzymaniowych należy także higiena kont. Pracownicy zmieniają stanowiska, odchodzą z firmy albo wracają po przerwie, a aplikacja musi odzwierciedlać te zmiany. Uprawnienia przypisuje się rolom, nie pojedynczym osobom, dzięki czemu przeniesienie pracownika sprowadza się do zmiany roli. Okresowy przegląd list kont wyłapuje konta nieaktywne oraz uprawnienia nadane doraźnie i nigdy nie wycofane. Gdy aplikacja korzysta z Active Directory, wiele z tych zmian wykonuje się w katalogu, a aplikacja tylko je odczytuje.

Monitoring dostępności i wydajności

Monitoring opiera się na dwóch rodzajach sygnałów. Testy aktywne co kilkadziesiąt sekund wywołują wybrany adres aplikacji i sprawdzają odpowiedź. Metryki pasywne pochodzą z działającego systemu: zużycie procesora, liczba żądań, odsetek błędów. Testy wykrywają awarię widoczną z zewnątrz, a metryki pokazują przyczyny, zanim użytkownicy odczują skutek.

WarstwaCo mierzyćSygnał alarmowy
Dostępnośćkod odpowiedzi adresu kontrolnego z punktu zewnętrznegokilka kolejnych prób bez odpowiedzi 200
Serwer aplikacjiprocesor, pamięć, odsetek odpowiedzi 5xxtrwały wzrost odsetka błędów
Baza danychczas zapytań, blokady, wolne miejsce na plikachzapytania powyżej ustalonego progu, brak miejsca
Certyfikat TLSdata wygaśnięciazbliżający się termin ważności
Kopie zapasowewynik zadania i wiek ostatniej kopiibrak nowej kopii w oczekiwanym oknie

ASP.NET Core udostępnia mechanizm kontroli stanu, który zwraca jeden adres z wynikiem zbiorczym. Poniższy przykład, poglądowy, sprawdza dostępność bazy danych i wystawia ścieżkę /health dla monitoringu. Szczegóły opisuje dokumentacja kontroli stanu w ASP.NET Core.

using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Diagnostics.HealthChecks;

public class BazaHealthCheck : IHealthCheck
{
    private readonly string _cs;
    public BazaHealthCheck(IConfiguration cfg) => _cs = cfg.GetConnectionString("Baza")!;

    public async Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext ctx, CancellationToken ct = default)
    {
        try
        {
            await using var cn = new SqlConnection(_cs);
            await cn.OpenAsync(ct);
            await using var cmd = new SqlCommand("SELECT 1", cn);
            await cmd.ExecuteScalarAsync(ct);
            return HealthCheckResult.Healthy();
        }
        catch (Exception ex)
        {
            return HealthCheckResult.Unhealthy("Baza niedostępna", ex);
        }
    }
}

// Program.cs
builder.Services.AddHealthChecks().AddCheck<BazaHealthCheck>("baza");
app.MapHealthChecks("/health");

Adres kontrolny potwierdza, że proces działa, ale nie że użytkownik wykona zadanie. Test syntetyczny loguje się kontem testowym, otwiera listę dokumentów i zapisuje próbny rekord, mierząc czas każdego kroku. Wyniki pokazują spowolnienia, które nie wywołują błędu HTTP, na przykład zapis trwający kilka razy dłużej niż zwykle. Konto testowe wymaga osobnych uprawnień, a jego dane trzeba oznaczyć jako próbne, aby nie zaburzały raportów.

Serwerownia z szafami serwerowymi i ekranami monitoringu jako zaplecze aplikacji webowej
Zaplecze serwerowe aplikacji - miejsce, w którym monitoring zbiera dane o dostępności i obciążeniu.

Logi i korelacja zdarzeń

Alarm mówi, że coś się stało, a dziennik zdarzeń wyjaśnia dlaczego. Przydatne są logi strukturalne, w których każdy wpis ma osobne pola: czas, poziom, użytkownik, identyfikator żądania. Ten sam identyfikator przechodzi przez wszystkie warstwy, więc analityk odnajduje w bazie zapytanie, które spowolniło konkretne kliknięcie. Zasady tworzenia dzienników w platformie .NET opisuje dokumentacja logowania w ASP.NET Core.

Zbyt czułe progi alarmów powodują, że zespół przestaje na nie reagować. Lepiej ustawić niewiele alertów, każdy z jasnym opisem pierwszego kroku diagnostycznego, niż rozsyłać wiadomości o każdym pojedynczym błędzie 500.

Kopie zapasowe i odtwarzanie bazy

W aplikacji z bazą SQL Server to baza przechowuje wartość biznesową: kod można wdrożyć od nowa z repozytorium, a utraconych dokumentów nie da się odtworzyć. Strategia kopii łączy kopie pełne z różnicowymi oraz z kopiami dziennika transakcji. Kopia dziennika rejestruje kolejne zapisy i pozwala wrócić do wybranej chwili, ale wymaga modelu odtwarzania FULL, który opisuje dokumentacja modeli odtwarzania w SQL Server.

Typ kopiiZawartośćWpływ na odtwarzanie
Pełnacała baza w chwili wykonaniapunkt wyjścia każdego odtworzenia
Różnicowastrony zmienione od ostatniej pełnejskraca łańcuch do odtworzenia
Dziennika transakcjizapisy od poprzedniej kopii dziennikawyznacza, ile danych można utracić
-- przykład poglądowy zadania SQL Agent, nazwy są umowne
BACKUP DATABASE AplikacjaProd
  TO DISK = N'\\serwer-kopii\sql\AplikacjaProd_FULL.bak'
  WITH CHECKSUM, INIT;

BACKUP DATABASE AplikacjaProd
  TO DISK = N'\\serwer-kopii\sql\AplikacjaProd_DIFF.bak'
  WITH DIFFERENTIAL, CHECKSUM, INIT;

BACKUP LOG AplikacjaProd
  TO DISK = N'\\serwer-kopii\sql\AplikacjaProd_LOG.trn'
  WITH CHECKSUM;

RESTORE VERIFYONLY
  FROM DISK = N'\\serwer-kopii\sql\AplikacjaProd_FULL.bak'
  WITH CHECKSUM;

Polecenie RESTORE VERIFYONLY sprawdza czytelność pliku, ale nie dowodzi, że baza da się uruchomić. Pełną pewność daje dopiero odtworzenie kopii na osobnym serwerze i sprawdzenie, czy aplikacja się z nią łączy. Składnię i opcje omawia dokumentacja kopii zapasowych i odtwarzania w SQL Server.

Reguła: kopia, której odtworzenia nie sprawdzono, jest jedynie założeniem, dlatego test odtworzenia należy do zadań zaplanowanych.

Parametry RPO i RTO

RPO (Recovery Point Objective) określa, ile danych firma może utracić, a RTO (Recovery Time Objective) - ile czasu może upłynąć do przywrócenia działania. Częstotliwość kopii dziennika wyznacza RPO: jeśli kopia powstaje co pół godziny, w najgorszym razie znikną zapisy z ostatnich trzydziestu minut. RTO zależy od rozmiaru bazy oraz przepustowości nośnika, a także od liczby kopii w łańcuchu. Zależność tych parametrów od modelu hostingu opisuje artykuł Magazyn w chmurze - architektura serwerowa. Oprogramowanie do kopii maszyn wirtualnych, w tym NAKIVO Backup, producent opisuje na stronie usługi kopii zapasowych.

Aktualizacje i wydania

Aplikacja stoi na kilku warstwach, z których każda ma własny cykl aktualizacji. System operacyjny serwera otrzymuje poprawki bezpieczeństwa, środowisko uruchomieniowe .NET i biblioteki zewnętrzne wydawane są w innym rytmie, a SQL Server publikuje zbiorcze aktualizacje. Do tego dochodzą wydania samej aplikacji. Zaniechanie poprawek narasta jak dług: im starsza wersja, tym trudniejsza i bardziej ryzykowna jedna duża zmiana.

WarstwaRyzyko aktualizacjiZabezpieczenie
System operacyjnyrestart serwera i niezgodność sterownikówokno serwisowe, wcześniejszy test na kopii środowiska
Środowisko .NET i bibliotekizmiana zachowania interfejsu programistycznegotesty automatyczne przed wdrożeniem
SQL Serverzmiana planów wykonania zapytańkopia pełna przed aktualizacją, porównanie czasów zapytań
Aplikacjabłąd w nowej wersji lub niezgodny schemat bazyplan wycofania, migracje wstecznie zgodne

Zmiany trafiają najpierw na środowisko testowe zbliżone do produkcyjnego i dopiero po akceptacji na produkcję. Na czas wdrożenia serwer IIS z modułem ASP.NET Core może pokazać użytkownikom stronę serwisową: umieszczony w katalogu aplikacji plik app_offline.htm zatrzymuje aplikację, a jego usunięcie ją uruchamia.

# poglądowy skrypt wdrożenia, ścieżki umowne
Copy-Item .\serwis.htm C:\inetpub\aplikacja\app_offline.htm
# ... kopia plików nowej wersji i uruchomienie migracji bazy ...
Remove-Item C:\inetpub\aplikacja\app_offline.htm

Migracje schematu bazy projektuje się tak, aby poprzednia wersja aplikacji mogła z nimi pracować. Dodanie kolumny z wartością domyślną jest bezpieczne, usunięcie kolumny już nie, więc takie zmiany rozkłada się na dwa wydania. Zasady pracy z zapytaniami i strukturą tabel opisuje artykuł o programowaniu baz danych, a wersjonowanie i aktualizacje po stronie dostawcy przedstawia przykład systemu TMS online.

Ochrona stacji i serwerów

Poprawki uzupełnia oprogramowanie ochronne. Na serwerach i stacjach stosuje się rozwiązania klasy XDR, które zbierają zdarzenia i pozwalają reagować na zagrożenia, na przykład ESET Inspect. Zakres tej usługi wraz z opisem wdrożenia przedstawia strona ESET bezpieczeństwo w ofercie SoftwareStudio. Oprogramowanie ochronne nie zastępuje aktualizacji: zamyka inną klasę ryzyka niż łatka na podatną bibliotekę.

Umowa SLA - czasy reakcji i naprawy

Umowa o poziomie usług (SLA, Service Level Agreement) zamienia oczekiwania w mierzalne zobowiązania. Zawiera kategorie zgłoszeń i godziny obsługi, a także czasy reakcji i usunięcia oraz sposób ich pomiaru. Bez takich zapisów spór o to, czy zgłoszenie było pilne, rozstrzyga się dopiero podczas awarii.

KategoriaSkutek dla firmyCo ustala umowa
Krytycznaaplikacja niedostępna dla wszystkich użytkownikównajkrótszy czas reakcji, możliwość obsługi poza godzinami pracy
Wysokafunkcja zablokowana, istnieje obejścieczas reakcji w godzinach obsługi, termin obejścia
Normalnabłąd bez wpływu na procestermin usunięcia w najbliższym wydaniu
Zmiananowe wymaganiewycena i harmonogram zamiast terminu naprawy

Reguła: czas reakcji i czas usunięcia to dwie osobne wartości - pierwsza dotyczy potwierdzenia i diagnozy, druga przywrócenia działania albo obejścia.

Dostępność wyrażona procentem

Umowy podają czasem dostępność jako procent miesiąca. Warto przeliczyć go na minuty, bo różnice okazują się większe, niż sugerują liczby. W miesiącu liczącym 30 dni mamy 43200 minut, z czego:

  • Dostępność 99 procent - dopuszcza łącznie około 432 minut niedostępności, czyli około 7,2 godziny.
  • Dostępność 99,9 procent - dopuszcza około 43 minut niedostępności w całym miesiącu.

W pomiarze trzeba ustalić, czy planowane okna serwisowe wliczają się do niedostępności oraz skąd pochodzi sygnał: z monitoringu zewnętrznego czy z dzienników aplikacji. Od tej decyzji zależy wynik tak samo jak od samej wartości procentowej.

Raport z realizacji usługi

Umowa serwisowa zyskuje na wartości, gdy wykonawca dostarcza cykliczny raport. Zestawia on liczbę zgłoszeń według kategorii oraz czasy reakcji i usunięcia w porównaniu z umową. Dodaje zdarzenia z monitoringu, które nie zakończyły się zgłoszeniem. Osobno wykazuje się incydenty powtarzające się, bo wskazują problemy do wyeliminowania w kolejnym wydaniu.

Kwartalny lub półroczny przegląd usługi jest okazją do zmiany parametrów, na przykład okien serwisowych i harmonogramu kopii. Aplikacja, która rośnie wraz z firmą, wymaga takiej rewizji, bo ustalenia z pierwszego wdrożenia przestają pasować do liczby użytkowników i wolumenu danych.

Monitor z dokumentacją techniczną i panelem parametrów systemu na tle miejskiej panoramy
Dokumentacja techniczna i historia zmian - podstawa przejęcia utrzymania przez kolejny zespół.

Rozwój po wdrożeniu i wiedza o kodzie

Po kilku miesiącach eksploatacji pojawiają się zmiany, których nie przewidziano w pierwszej specyfikacji. Prowadzi się je jako zamawiane wydania: zgłoszenia trafiają do listy zadań, wykonawca szacuje pracochłonność, a zamawiający ustala kolejność. Proces wytwarzania takich wydań opisuje artykuł o producencie aplikacji webowych i potoku wdrożeniowym, natomiast wpływ zmian na dane zewnętrzne zawiera tekst o integrowaniu aplikacji webowych.

Ryzyko utrzymania rośnie, gdy wiedza o systemie jest w głowie jednej osoby. Ograniczają je dwa narzędzia: repozytorium z historią zmian i dokumentacja techniczna. Trzecim zabezpieczeniem są przeglądy kodu przed scaleniem zmian. Dokumentacja obejmuje architekturę oraz konfigurację środowisk, a nie tylko opis funkcji dla użytkowników. Ustalenie, kto ma dostęp do kodu źródłowego i na jakich zasadach, należy do umowy równie mocno jak zakres funkcji.

Dług techniczny i testy regresji

Każde szybkie obejście zostawia dług techniczny, który po kilku wydaniach zaczyna spowalniać kolejne zmiany. Zespół utrzymaniowy rezerwuje więc część czasu na porządkowanie kodu i uzupełnianie testów. Testy regresji, czyli zestaw automatycznych sprawdzeń krytycznych ścieżek, pozwalają wdrażać poprawki z mniejszą obawą, że naprawa jednego błędu zepsuje inną funkcję.

Ogólną architekturę takich programów opisuje artykuł o aplikacji webowej od przeglądarki po bazę danych, a wprowadzenie do zagadnienia zawiera tekst o dedykowanych aplikacjach webowych.