Subsections


4 Projekt systemu


1 Technologie

W tym podrozdziale znajduje się opis technologii i produktów użytych przy realizacji systemu, wraz z uzasadnieniem dokonanego wyboru. W większości wypadków prezentowałem też konkurencyjne technologie i dokonywałem krótkiego porównania między dostępnymi możliwościami. Głównymi kryteriami przy wyborze technologii były: Choć decyzje dotyczące technologii można podjąć dopiero na etapie implementacji, to wcześniejsze wybranie używanych języków programowania, platformy systemowej itp. pozwala na precyzyjniejsze zaprojektowanie systemu. Przed rozpoczęciem etapu projektowania chciałem więc wybrać: technologie do obsługi dynamicznych stron WWW (serwer WWW, język generowania stron); system bazy danych; język programowania, w którym zostanie zaimplementowany system sprawdzania stron oraz mechanizm komunikacji między elementami systemu. W kolejnych podpunktach omawiam poszczególne technologie i produkty.

1 Dynamiczne strony WWW

Dynamiczne strony WWW są głównym (poza pocztą elektroniczną) interfejsem całego serwisu, jego sposobem komunikacji z użytkownikami. Będą one działały na serwerze HTTP Apache. Serwer ten jest aktualnie jednym z najbardziej rozpowszechnionych serwerów WWW, używanym w szeregu zastosowań, bezpiecznym, stabilnym i wydajnym. Dodatkową jego zaletą jest to, iż Apache jest produktem darmowym.

Apache działa świetnie w połączeniu z także bezpłatnym systemem operacyjnym Linux. Zamierzam wykorzystać dystrybucję Linuxa RedHat 7.2. Wybór dystrybucji nie jest istotny, gdyż wszystkie one są ze sobą zgodne (przynajmniej na tyle, aby zmiana dystrybucji w przyszłości nie pociągała za sobą konieczności modyfikacji kodu źródłowego serwisu czy konfiguracji serwera WWW).

Strony WWW zostaną zaimplementowane w języku skryptowym PHP (w wersji 4). Wybór języka do generowania dynamicznych stron nie jest tak prosty jak wybór serwera, gdyż kontrkandydaci (Perl, servlety Java, JSP, XSP, Python i inni) także spełniają wszystkie (lub prawie wszystkie) wymienione warunki. Należy jednak pamiętać, że serwis internetowy jest tylko drobną częścią całego systemu i będzie się składał z najwyżej kilkunastu stron. Tak nieduży serwis można łatwo i szybko zaimplementować właśnie w PHP, najbardziej nadającym się do takich zastosowań.

2 Baza danych

Baza danych będzie w systemie elementem łączącym serwis internetowy (dynamicznie generowane strony WWW będące interfejsem użytkownika) oraz oprogramowanie do sprawdzania śledzonych stron. W bazie danych trzymane będą informacje o użytkownikach, stronach, wynikach sprawdzania itp. W projektowanym przeze mnie systemie skorzystam z bazy danych Postgres. Produkt ten jest darmowy, szeroko rozpowszechniony i często wykorzystywany na platformie Linux w połączeniu z językiem PHP.

Główny rywal bazy danych Postgres to MySQL, również spełniająca podane wymogi. MySQL jest uważany za nieco bardziej wydajny od bazy Postgres. Postgres oferuje jednak więcej dodatkowych własności, takich jak obsługa transakcji czy wewnętrzny język do tworzenia procedur składowanych (ang. stored procedures -- procedur i funkcji działających wewnątrz bazy danych). Obie te cechy mogą się jednak bardzo przydać przy tworzeniu systemu rozproszonego. Wykorzystanie transakcji umożliwi zapewnienie spójności bazy danych. Natomiast podprogramy zapisane i działające w bazie pozwolą między innymi uniknąć dublowania kodu na poziomie programów (np. ten sam kod w oprogramowaniu serwera głównego oraz węzła) oraz poprawią wydajność działania bazy danych.

Cały system powinien być tak zaprojektowany i zaimplementowany, aby w razie potrzeby umożliwić zmianę serwera bazodanowego. Dlatego też wyboru bazy Postgres nie traktuję jako ostatecznego.

3 Oprogramowanie sprawdzające strony WWW

Oprogramowanie do sprawdzania śledzonych stron zostanie napisane w języku Java w wersji J2EE 1.4. Wybór ten jest podyktowany szeregiem istotnych powodów: Pomimo tego, że istnieje bardzo wiele aktualnie używanych języków programowania, wybór języka Java był dla mnie w praktyce oczywisty. Jedynym poważnym konkurentem dla środowiska Java jest stworzona i promowana przez firmę Microsoft platforma .NET. Oferuje ona wiele zaawansowanych bibliotek, możliwość używania różnych języków programowania (między innymi podobnego do Java języka C#) oraz łatwą integrację z innymi produktami Microsoft (systemem operacyjnym, bazą danych, serwerem wymiany informacji itp.). Jednak wybór .NET ma dwie podstawowe wady. Po pierwsze platforma ta jest produktem komercyjnym. Drugim minusem jest to, iż działa ona jedynie w połączeniu z systemem operacyjnym firmy Microsoft.


4 Komunikacja pomiędzy elementami systemu

Serwer główny będzie komunikował się z węzłami poprzez sieć Internet. Wybór metody komunikacji nie jest oczywisty z powodu dużej liczby możliwości: Jak zwykle w takich sytuacjach, każda z opcji ma swoje plusy i minusy. Należy więc wybrać tę, która najlepiej spełnia wymagania i nakłada najmniej ograniczeń. Przesyłanie tekstowych komunikatów poprzez zwykłe połączenie TCP/IP jest najprostszym rozwiązaniem, które jednak oznacza dla programisty konieczność ciągłego utrzymania połączenia (jeśli połączenie TCP/IP zostanie przerwane, trzeba je na nowo nawiązać). Inne problemy, które mogą się pojawić przy implementowaniu tego rozwiązania, to konieczność sprawdzenia, czy odebrany komunikat jest spójny oraz czy jest zakodowany w spodziewanym formacie. Druga z wymienionych wad nie występuje, gdy komunikaty będą przesyłane w formacie XML. W takim przypadku do sprawdzenia poprawności formatu danej wiadomości można skorzystać z istniejących parserów XML. Wykorzystanie formatu XML pozwoliłoby na szczegółowe zdefiniowanie i na przykład opublikowanie struktury każdej wiadomości. Dzięki tak sformalizowanemu protokołowi komunikacji możliwe byłoby w przyszłości stworzenie dodatkowego oprogramowania węzłów. Jednak stwarzanie takiej możliwości nie ma większego sensu, gdyż oprogramowanie węzłów musi być zaimplementowane w języku Java, tak aby kod klasy realizującej dany typ zadania mógł być ściągany z serwera i uruchamiany na węzłach.

Ponieważ oprogramowanie serwera głównego i węzłów będzie napisane w obiektowym języku, zamiast niskopoziomowej komunikacji po TCP/IP można wykorzystać jeden z mechanizmów zdalnego wywołania metod w obiektach istniejących na innym serwerze. Dostępne mechanizmy, które rozpatrywałem, to SOAP (ang. Simple Object Access Protocol), CORBA (ang. Common Object Request Broker Architecture) oraz RMI (ang. Remote Method Invocation). Przy standardowym użyciu wszystkie te technologie oferują komunikację w jedną stronę: metody dostępnej zdalnie klasy są wołane przez obiekty działające na innych komputerach. Aby obie strony mogły inicjować komunikację, należałoby na obu współpracujących komputerach uruchomić serwer zdalnych obiektów. Aby nie komplikować niepotrzebnie komunikacji między elementami systemu, można tak zaprojektować protokół komunikacji między nimi, aby wystarczyło zdalne wołanie metod w obiektach tylko jednego z porozumiewających się programów.

Użycie protokołu SOAP jest kuszące, gdyż wykorzystuje on znane i powszechnie stosowane technologie: HTTP oraz XML. Serwer SOAP można uruchomić jako tzw. plug-in w serwerze HTTP Apache -- nie trzeba więc otwierać żadnego nowego portu poza portem 80 (HTTP). Niemniej jednak jedna z głównych zalety protokołu SOAP -- możliwość zaimplementowania klienta i serwera w różnych językach oprogramowania i na różnych platformach systemowych -- traci znaczenie przy wyborze języka Java do implementacji całego oprogramowania. Ponadto przy zdalnym wywołaniu metody, gdy wewnętrznie wbudowany mechanizm sam zapewnia sprawdzanie spójności wywołania, możliwość korzystania z formatu XML staje się raczej koniecznością, dodatkowym obciążeniem. Parametry przekazywane przy wołaniu metod są ograniczone do prostych typów, co uniemożliwia przekazywanie obiektów.

Podobnie rzecz ma się z technologią CORBA, będącą w powszechnym użyciu w dużych systemach rozproszonych. Leżąca u podstaw protokołu CORBA architektura pozwala na zdalne udostępnianie obiektów oraz wołanie ich metod przy użyciu identyfikatora obiektu bez wskazywania, na której maszynie obiekt się znajduje. Funkcjonalność ta jest nieprzydatna z punktu widzenia tworzonej przeze mnie biblioteki, ponieważ algorytm do równoważenia obciążenia powinien ściśle kontrolować przydział zadań do węzłów.

Wymienionych wcześniej wad technologii SOAP i CORBA nie ma protokół RMI ([Gro01]). Jest to protokół zdalnego wołania metod dla klas w języku Java. Dzięki temu umożliwia on wykorzystanie możliwości tego języka takich jak automatyczne ładowanie klas poprzez protokół HTTP, przekazywanie obiektów w parametrach wywołania metod czy definiowanie interfejsów zdalnych obiektów w standardowym formacie Java (a nie np. IDL wbudowanym w technologię CORBA). Używanie protokołu RMI nie nastręcza programiście większych trudności. Korzystanie z niego wydaje się być relatywnie prostsze niż z technologii CORBA (ze względu na skomplikowaną architekturę) czy SOAP (konieczność używania formatu XML). Fakt, że RMI zostało zaprojektowane właśnie dla języka Java sprawia, iż jest to najlepszy -- spośród mechanizmów zdalnego wołania metod -- wybór dla rozproszonych aplikacji implementowanych w tym języku.

Zupełnie innym od rozważanych wcześniej sposobów komunikacji w systemie jest komunikowanie się poprzez zawartość wspólnej bazy danych. W uproszczeniu taka komunikacja w systemie sprawdzania stron WWW działałaby następująco: serwer główny zostawia w bazie danych informacje, które strony mają być sprawdzone i przez które węzły (np. w postaci zaznaczonych flag na odpowiednich rekordach). Następnie oprogramowanie węzła łączy się z bazą danych i pobiera informacje o przydzielonych sobie stronach. Po ich sprawdzeniu umieszcza wyniki w odpowiedniej tabeli, z której pobiera je serwer główny. Problemem jest jednak zsynchronizowanie działań serwera głównego i węzłów -- w jaki sposób węzeł ma wiedzieć, że nowo przydzielone zadania czekają na niego w bazie danych? Rozwiązaniem, z oczywistych powodów nienajlepszym, byłoby cykliczne sprawdzanie zawartości bazy danych. Plusem takiej metody komunikacji jest natomiast jej trwałość i odporność na błędy. Komunikat w bazie danych nie musi być natychmiast odebrany przez adresata, może czekać na moment, w którym program odbierający zostanie uruchomiony i połączy się z bazą danych. Taka funkcjonalność znacznie ułatwiłaby zapewnienie odporności systemu na błędy (np. czasowe wyłączenia węzłów lub przerwanie komunikacji). Informacje przekazywane przez bazę danych mają własności asynchronicznych wiadomości. W praktyce taką metodę komunikacji można by zakwalifikować jako komunikację opartą na wiadomościach (ang. message-oriented communication).

Z powodu wymienionych wad baza danych nie może być jedynym sposobem komunikowania się elementów systemu. Niezbędne, a przynajmniej bardzo pomocne, wydaje się użycie synchronicznego sposobu komunikacji. W implementowaniu biblioteki do równoważenia obciążenia użyję protokołu RMI jako najwygodniejszej z omówionych możliwości. Natomiast wszelkie istotne dla działania systemu informacje będą także zapisywane na bieżąco w bazie danych, co umożliwi proste odtworzenie stanu pracy w przypadku awaryjnego przerwania działania i ponownego uruchomienia jednego z programów. Baza danych będzie zawierać tzw. dane rekonstrukcji (por. [Cou98]). Oznacza to, że system będzie wykorzystywał bazę danych jako awaryjny środek komunikacji. Przykładowo, serwer będzie zapisywał w bazie danych informacje o aktualnym cyklu, postępach w realizacji zadań, przypisaniach poszczególnych zadań do węzłów itp. Te informacje będą bezcenne w przypadku awarii serwera -- po ponownym uruchomieniu nie będzie on żądał od węzłów powtórnego wykonania zrealizowanych wcześniej zadań.


2 Budowa systemu

System sprawdzania stron WWW będzie systemem rozproszonym -- będzie się składał z programów współpracujących ze sobą, działających na połączonych siecią komputerach. System będzie przejrzysty (ang. transparent), co oznacza, że fakt jego rozproszenia nie będzie z zewnątrz widoczny. Patrząc z boku, system będzie się zachowywał jak pojedynczy program.

Programy sprawdzające strony WWW będą tworzyć scentralizowaną sieć. Schemat połączeń w systemie pokazano na rys. 4.1. Punktem centralnym, sterującym działaniem całego systemu, jest serwer główny. Zajmuje się on koordynowaniem pracy węzłów: rozdziela pomiędzy nie strony do sprawdzania i odbiera wyniki tego sprawdzania. Każdy z węzłów odbiera od serwera głównego listę stron, łączy się z odpowiednimi serwerami WWW, sprawdza, czy śledzone strony się zmieniły, po czym odsyła wyniki do serwera głównego.

Rysunek 4.1: Topologia systemu

Scentralizowana struktura połączeń nie jest oczywiście jedyną, która mogłaby być zastosowana przy budowie takiego systemu. Spośród innych często wykorzystywanych topologii można by wymienić pierścień z żetonem (ang. token-ring -- szereg równoważnych komputerów połączonych w koło), sieć hierarchiczną (drzewo sieci scentralizowanych -- węzeł może być jednocześnie ojcem podsieci) czy sieć równoważną (ang. peer-to-peer -- komputery połączone ze sobą bez wyraźnej struktury, komunikujące się bezpośrednio). Istnieje także wiele kombinacji podstawowych topologii. Mój wybór jest jednak uzasadniony tym, że scentralizowana sieć ma następujące zalety: Inne z wymienionych architektur nie mają przynajmniej części tych plusów. Żadna z nich nie jest tak prosta do zaimplementowania oraz administracji. Należy przy tym pamiętać, że łatwość zaimplementowania danego rozwiązania nie jest jedynie kwestią wygody programisty. Ma ona bezpośredni wpływ na możliwość zastosowania i używania skutecznej strategii bezpieczeństwa, na łatwość wprowadzania w przyszłości zmian w systemie itp.

Z wyborem architektury scentralizowanej wiążą się też pewne minusy, o których należy pamiętać i tak zaprojektować oraz zaimplementować system, aby ich efekty były minimalne. Jedną z wad tej topologii jest ograniczona skalowalność. Do scentralizowanego systemu nie można przyłączać bardzo dużej liczby węzłów, gdyż jego wydajność zacznie być ograniczana przez przepustowość serwera głównego. Jednak biorąc pod uwagę, że liczba węzłów nie przekroczy kilkudziesięciu (por. punkt 3.3.2), można założyć, iż w zupełności wystarczy jeden serwer główny.

Innym minusem scentralizowanej topologii jest mała odporność na błędy. Wystarczy wyłączyć serwer główny, aby cały system przestał działać. Problem ten jest w literaturze (np. [Tan02]) nazywany pojedynczym punktem błędu (ang. single point of failure). Tej wady nie da się całkowicie ominąć, lecz należy zminimalizować jej skutki, realizując wymagania omówione w punkcie 3.3.4. W szczególności oprogramowanie serwera głównego będzie w stanie, po ponownym uruchomieniu, podjąć pracę w przerwanym momencie. Projekt budowy programu głównego zamieszczono w punkcie 4.5.

Wśród pożądanych cech systemów rozproszonych często wymienia się także niemożność prostego wyłączenia systemu np. w efekcie nacisków politycznych lub wyroków sądowych. Taką odporność wykazują sieci równoważne, w których węzły komunikują się ze sobą nawzajem bez pomocy żadnego wyróżnionego serwera. Przykładem tak zbudowanych systemów jest Freenet oraz Gnutella. W przypadku systemu sprawdzania stron WWW taka własność nie ma większego znaczenia (trudno wyobrazić sobie przyczynę, dla którego serwis musiałby zostać zamknięty z powodów prawnych). Przy innych zastosowaniach biblioteki do rozdzielania zadań ta cecha mogłaby się okazać pożądana. Niestety, w przypadku architektury scentralizowanej zapewnienie takiej własności jest praktycznie niemożliwe -- aby unieruchomić cały system, wystarczy wyłączyć serwer główny.


3 Baza danych

Baza danych zawierać będzie informacje wykorzystywane zarówno przez bibliotekę do przetwarzania rozproszonego, jak i kod zajmujący się sprawdzaniem stron WWW. Informacje te będą ze sobą powiązane relacjami. Cześć tabel, przechowująca ogólne informacje o systemie, węzłach i zadaniach, będzie dostępna dla całego systemu. Natomiast tabele z danymi specyficznymi dla wykonywanego typu zadania wykorzystywane będą jedynie przez kod zajmujący się realizacją tego zadania. Biblioteka do równoważenia obciążenia oczywiście nie może się odwoływać do tabel opisujących konkretne zadania, gdyż nie posiada na ich temat żadnych informacji. Tabele te tworzy dopiero programista korzystający z gotowej, istniejącej biblioteki.

Podstawowe tabele znajdujące się w bazie danych oraz relacje między nimi przedstawiono w postaci diagramu DRD (ang. Data Relationship Diagram) na rys. 4.2. Diagram ten jest podzielony na dwie części: powyżej przerywanej linii znajdują się tabele z ogólnymi informacjami o zadaniach, węzłach itp. Struktura tej części bazy danych jest niezależna od typu wykonywanego przez system zadania. W ich przypadku stosowałem nazewnictwo angielskie. Natomiast poniżej niebieskiej linii widać tabele związane konkretnie ze śledzeniem i sprawdzaniem stron WWW - tabele te mają nazwy w języku polskim.

Rysunek 4.2: Podstawowy schemat bazy danych

Tabele przedstawione na rys. 4.2 zawierają następujące dane: Relacje pomiędzy tabelami to zwykle relacje typu "jeden do zero-lub-wiele". Tabele FamilyOnNode, JobOnNode oraz Sledzenie umożliwiają zaimplementowanie w bazie danych połączeń typu "wiele do wielu" -- odpowiednio między tabelami Family i Node, Job i Node oraz Strona i Osoba. Tabele te oprócz indeksów rekordów w tabelach nadrzędnych przechowują także dodatkowe informacje. Przykładowo w tabeli Sledzenie znajduje się pole od_kiedy, mówiące kiedy dany użytkownik rozpoczął śledzenie danej strony.

Relacje typu "jeden do jednego" lub "jeden do zero-lub-jeden" łączą tabelę Job z tabelami opisującymi szczegółowo dane zadanie. W przypadku systemu sprawdzania stron są to tabele Strona oraz Osoba. Tabela Strona zawiera informacje niezbędne do sprawdzania strony WWW. Natomiast tabela Osoba będzie przydatna do wysyłania powiadomień (wysyłanie listów elektronicznych z informacją o zmianie stron będzie drugim obok sprawdzania stron typem zadania wykonywanym przez bibliotekę -- patrz punkt 5.3). Relacje łączące te tabele są typu "jeden do zero-lub-jeden". W przypadku relacji łączącej Job i Strona każdy rekord w tabeli Strona ma odpowiednik w tabeli Job, choć rekord w tabeli Job może nie być związany z żadnym rekordem w tabeli Strona.


4 Biblioteka do rozproszonego przetwarzania zadań

Częściowo wyodrębnionym fragmentem systemu będzie biblioteka do rozdzielania i rozproszonego przetwarzania zadań. Bibliotekę tę nazwałem JODL od skrótu angielskiej nazwy Job Dispatching Library. Biblioteka JODL nie jest programem samym w sobie, oferuje ona jedynie pewną funkcjonalność. Programy korzystające z biblioteki wywołują jej metody oraz podsuwają bibliotece własne klasy z kodem realizującym zadania (i inne, opisane w punkcie 4.4.2). Uproszczony diagram interakcji pokazujący wykorzystanie biblioteki znajduje się na rysunku 4.3.

Rysunek 4.3: Diagram interakcji

Biblioteka będzie działać w cyklach. Cykle mają kolejne numery, zapisywane w tabeli Run. Pojedyncze uruchomienie metody realizującej zadania z danej grupy (ang. family) to jeden cykl, czyli jednorazowe wykonanie wszystkich zadań z tej grupy.


1 Zadania realizowane przez bibliotekę

Informacje o zadaniach będą trzymane w bazie danych (patrz punkt 4.3). W każdym cyklu biblioteka będzie pobierać z bazy danych wszystkie zadania z danej grupy. Następnie każde z zadań będzie wykonywane na odpowiednim węźle (sposób przydziału zadań do węzłów jest opisany w punkcie 4.4.2). Wykonanie zadania z punktu widzenia biblioteki polega na wywołaniu odpowiedniej metody.


2 Algorytm rozdzielania zadań

Główną częścią biblioteki do rozdzielania zadań stanowi algorytm decydujący o przydziale poszczególnych zadań do węzłów systemu. Przydział ten będzie dynamiczny z oczywistych, opisanych wcześniej przyczyn. Algorytm musi wybrać węzeł dla zadania w dwóch sytuacjach: gdy zadanie jest nowe, właśnie pojawiło się w systemie, lub gdy istniejące już zadanie zmienia (z różnych powodów) węzeł, na którym jest wykonane. Wraz z biblioteką dostępna jest klasa implementująca prosty algorytm przydziału zadań do węzłów. Wybiera ona węzeł, któremu najprawdopodobniej najkrócej zajmie wykonanie danego zadania. Czasu tego nie da się dokładnie wyliczyć ani nawet łatwo oszacować. Średni czas realizacji z ostatnich cykli nie wystarcza, gdyż część zadań może nie być wykonywana w każdym cyklu. Opieranie wyboru na liczbie już przypisanych zadań do danego węzła jest niepewne z dwóch powodów: wspomnianego wcześniej oraz różnych czasów wykonania poszczególnych zadań. Ostatecznie, aby dokonać jak najlepszego przydziału, algorytm przydziału ocenia każdy węzeł korzystając równocześnie z wszystkich dostępnych informacji: Oczywiście klasa z implementacją podstawowego algorytmu przydzielania zadań do węzłów przy wyborze węzła nie może się kierować żadną szczegółową wiedzą o danym zadaniu. Klasa ta takiej wiedzy po prostu nie posiada, gdyż jest częścią ogólnej biblioteki. Aby uzależnić przydział od konkretnego typu zadania, programista może stworzyć klasę implementującą własny algorytm i podstawić ją bibliotece zamiast klasy domyślnej. Przykładowo, jeśli z jakiegoś powodu strony w domenie .org powinny być sprawdzane zawsze przez arbitralnie wyznaczony węzeł, wystarczy odpowiednio zaimplementować metodę przydziału zadań do węzłów, uwzględniającą ten warunek. Własną klasę z implementacją tej metody można podstawić tak, aby była wykorzystywana przy rozdzielaniu wszystkich zadań lub np. zadań tylko z wybranej grupy.

W określonych przypadkach istniejące zadanie, przypisane już do jakiegoś węzła, może zostać na nowo przypisane do innego węzła. Możliwe przyczyny takiej zmiany są następujące:

Zmiana przypisania zadania może być próbna lub stała. Zmiana próbna to taka, która jest dokonywana tymczasowo, prawdopodobnie jednorazowo. Przykładowo, gdy węzeł nie jest dostępny w danym cyklu wykonywania zadań, jego zadania są przenoszone na inne węzły. Ponieważ zmiana przypisań jest próbna, w momencie, gdy węzeł ten zacznie działać ponownie, wrócą do niego zadania wcześniej na nim wykonywane. Potraktowanie węzła, który zaczął ponownie działać, jak nowego węzła świeżo podłączonego do systemu byłoby błędne, gdyż wiązałoby się z utratą przypisań wypracowanych przez przenoszenie zadań podczas poprzednich cykli. Natomiast do nowego węzła zadania są przypisywane (najczęściej) losowo.

Zmiana próbna może zostać wycofana lub utrwalona (przejść na zmianę stałą). Zmiana jest wycofywana, gdy węzeł poprzednio wykonujący dane zadanie staje się ponownie dostępny i gdy okazuje się, że nowy węzeł mniej efektywnie wykonuje to zadanie. Natomiast zadanie zmienia węzeł na stałe, gdy poprzedni węzeł przestaje być definitywnie dostępny lub gdy przeniesienie zadania okazuje się być efektywne (tzn. zadanie jest wykonywane wyraźnie szybciej lub skuteczniej na nowym węźle niż na starym).

Działanie algorytmu można modyfikować przez odpowiednią zmianę jego ustawień i parametrów. Najważniejsze z nich to:


3 Protokół komunikacji wewnątrz systemu

Komunikacja w systemie będzie się odbywała pomiędzy serwerem głównym a każdym z węzłów. Na tą komunikację składają się następujące wiadomości:
a.
serwer inicjuje agenta (tzn. wysyła informacje o bazie danych, numerze cyklu, klasie realizującej zadanie itp.),
b.
serwer wysyła agentowi zadania, które mają być przez niego zrealizowane,
c.
agent odsyła serwerowi informacje o zadaniach, które wykonał,
d.
agent odsyła serwerowi informacje o zadaniach, których nie mógł zrealizować,
e.
serwer pyta agenta, ile zostało mu jeszcze zadań do wykonania,
f.
serwer prosi agenta o odesłanie części z zadań, które jeszcze nie zostały wykonane (aby móc je przekazać innemu agentowi).
Jak zostało już powiedziane w punkcie 4.1.4, podstawowym mechanizmem komunikacji w systemie będą zdalne wywołania metod poprzez RMI. Mechanizm ten w podstawowym użyciu zapewnia komunikację w jedną stronę. Z powyższej listy typów przesyłanych wiadomości wynika, że większość z nich jest inicjowana przez serwer. Jedynie informacje o wynikach realizowania zadań są wysyłane z inicjatywy agenta (punkty c. i d.). Czy potrzebna jest więc komunikacja w dwie strony? Wydaje się, że nie ma takiej konieczności. Łatwiej z punktu widzenia serwera będzie okresowo pytać każdego agenta o wyniki, zamiast oczekiwać, że agent sam je odeśle w nieokreślonym momencie. Punkty c. i d. można więc zmienić na następujące:
c.
serwer pyta agenta o wykonane już przez niego zadania,
d.
serwer pyta agenta o zadania, których agent nie mógł zrealizować.
Dzięki temu wszystkie typy komunikatów są inicjowane przez serwer. Serwer, wywołując metody obiektów działających na węzłach, ma kontrolę nad wymianą informacji w systemie.


4 Klasa serwera głównego

Główną klasą biblioteki jest klasa serwera, odpowiedzialna za rozdzielanie zadań, wysyłanie ich do węzłów oraz odbieranie wyników. Wykorzystanie biblioteki wiąże się z wołaniem metod tej właśnie klasy. Prosty przykład wykorzystania jej możliwości znajduje się w dodatku A, dlatego nie ma sensu go powielać. Natomiast w tym punkcie chcę opisać wewnętrzny mechanizm jej działania.

Klasa serwera głównego działa w jednym wątku. Udostępnia ona metodę, która zajmuje się:

Następnie w pętli są wykonywane następujące czynności: Pętla ta działa do momentu, w którym lista zadań do zrealizowania w tym cyklu będzie pusta. W ten sposób po zakończeniu działania pętli wszystkie zadania są zrealizowane (bądź zostały podjęte próby ich zrealizowania na więcej niż jednym węźle) oraz dokonano zmiany przypisań zadań do węzłów tak, jak to opisano w punkcie 4.4.2.

Stan realizacji zadań jest na bieżąco zapisywany w bazie danych, co pozwala w prosty sposób odtworzyć działanie klasy serwera głównego po jej awaryjnym przerwaniu. Służy do tego będzie oddzielna metoda.


5 Aplikacja sprawdzająca strony WWW

Aplikacja sprawdzająca strony WWW i wysyłająca powiadomienia do użytkowników jest głównym programem systemu CoNowego.pl, działającym na serwerze głównym. Jest ona uruchamiana cyklicznie (aktualnie raz na dobę). Podczas każdego uruchomienia aplikacja sprawdza wszystkie śledzone przez użytkowników strony, a następnie wysyła listy z powiadomieniami o zmianach zawartości stron. Kolejne czynności wykonywane przez program to: Program serwer musi umieć sobie radzić z sytuacjami, gdy jego działanie zostało przerwane w błędny sposób. W trakcie działania po ukończeniu kolejnych czynności zapisuje on w bazie danych odpowiednie informacje. W przypadku awaryjnego przerwania działania i ponownego uruchomienia, program korzystając z zapisanych informacji będzie w stanie kontynuować pracę w przerwanym momencie. Dzięki analogicznej funkcjonalności w bibliotece JODL, zaimplementowanej w metodzie rerun(), w przypadku gdy działanie programu zostanie przerwane w trakcie sprawdzania stron, przy ponownym uruchomieniu sprawdzone zostaną tylko strony niesprawdzone wcześniej.
Sebastian Łopieński