Programowanie w języku Delphi » Artykuły

Service Application

Jeśli masz aplikacje, która ma za zadanie tylko przetwarzanie danych, lub dziala w inny sposób nie wymagający interakcji z użytkownikiem, to dobrym rozwiązaniem jest przekształcenie Twojego programu w usługę serwisową (oczywiście jesli działa w sieci).
Jak to zrobić?
Dość prosto - z menu >File< wybierz >New<, a nastepnie >Service Application<. Delphi utworzy automatycznie wszystko co potrzeba, a w szczególności formę >TSerwice<. Ważne jest, aby nie dodawać do projekty żadnych tForm - spowoduje to wewnętrzny błąd.

Podstawą działania naszej usługi będzie zdarzenie >onExecute<, któremu przypisujemy kod:

Timer1.Enabled := True;
 while not Terminated do
    ServiceThread.ProcessRequests(True);
  Timer1.Enabled := False;


Jak widzimy, potrzebny też będzie TTimer, który początkowo jest nieaktywny. W zdarzeniu >onTimer< umieszczamy kod naszej aplikacji.

Aby zainstalować-zarejestrować serwis w Windows - w wierszu poleceń wpisz:
nazwaprogramu.exe /INSTALL
Po tym wystarczy ustawić parametry pracy usługi (panel sterowania/opcje administracyjne/usługi).

Teoretycznie to wszystko, jednak istnieje kilka pułapek...

Jeśli nasz projekt zawiera jakikolwiek komponent połączenia z bazą danych, to jego początkowy stan musi być nieaktywny - jest wysoce prawdopodobne, że nasza usługa uruchomi się (po restarcie systemu) przed uruchomieniem bazy danych (np. MySQL) i w wyniku błędu nasza usługa nie wystartuje.

Ja rozwiązałem to w następujący sposób:
Timer1.Interval ustawiam na 10000 aby dać czas na uruchomienie MySQL, można dobrać eksperymentalnie...
>onTimer< zawiera na samym początku następujący kod:
while not Mysql.Connected do
try
MySQL.Connect;
Table1.Active := true;
Table2.Active := true;
except
// nie jest konieczne
ShowMessage('Brak połączenia z serwerem MySQL'); 
end;


Jak widzimy, wykonanie zasadniczego zadania usługi czeka na połączenie z MySQL. Jest to dodatkowe zabezpieczenie na wypadek, gdyby z jakiejś przyczyny połączenie z bazą zostało utracone.


Na wstępie napisałem, że nasza usługa nie wymaga interakcji z użytkownikiem - nie jest to do końca prawda - tak jak w przypadku każdej innej usługi mamy możliwość przesłania do niej danych - a więc w pewnym stopniu sterowania jej przebiegiem. Jak to zrealizować?
Sposobów jest wiele - opiszę dwa:

1. Tworzymy tabelę, do której wstawiać będziemy rekordy - usługa przy każdym przebiegu odczytuje nowe wpisy, a nastepnie wykonuje zawarte w nich instrukcje.

2. Używamy TServerSocket po stronie usługi, a TClientSocket w aplikacji monitorującej/sterującej, a polecenia sterujące usługą przesyłamy za ich pomocą (artykuł omawiający używanie gniazd jest na 4programmers.net).

Ja wybrałem oba sposoby :)

W tabeli mam rekordy zawierające poszczególne procedury przetwarzania, a pole >status< informuje o tym, czy dana procedura ma być wykonywana. W ten sposób można wpływać na zakres przetwarzania wykonywany przez usługę, a także kolejność wykonywanych procedur (pole 'rank' z indeksem).

Gniazd natomiast używam do przesłania instrukcji innej natury - głównie jest to wstrzymanie/wznowienie działania usługi, przesyłam kody sterujące które wywołują np.
Service1.DoPause;
Service1.DoContinue;
W ten sposób moge też pobrać coś w rodzaju raportu o obecnym stanie usługi/przetwarzania.

Jaki zysk, skoro i tak komunikuje się z usługą z klienta sieci?
W moim przypadku zyskiem jest bardzo istotne ograniczenie ruchu w sieci - te same zadania realizowane na komputerze-kliencie, jako zwykła aplikacja generowały ogromny ruch w sieci - dane które są przesyłane do MySQL z kilkunastu komputerów niemal w całości wędrowały na komputer z aplikacją przetwarzającą, gdzie po zrobieniu co trzeba wędrowały z powrotem na serwer... Teraz pobieram tylko raporty, wyłącznie na żądanie, czyli dość sporadycznie, a sam raport to nie więcej jak kilkadziesiąt kb, czyli drobiazg. Serwer jest też dość silną maszyną, to samo przetwarzanie wykonuje się w czasie znacząco szybszym.

5 komentarzy

adrianc19 2005-10-31 12:35

Już znalazłem rozwiązanie: jeżeli ktoś potrzebuje to jest tu w j. Angielskim: http://builder.com.com/5100-6387_14-1050538.html?tag=search

adrianc19 2005-10-31 10:59

Chciałbym wiedzieć czy tą usługe trzeba jakoś zarejestrować i względnie jak, żeby się uruchamiała i pokazała w oknie usługi lokalne, jest mi to dość potrzebne a nigdzie nie znalazłem sensownego opisu do tego...

therifler 2005-09-07 22:36

Sory ale jak ja miałem personal 7 to chyba to miałem... bo wtedy czat pisałem i aplikacje serverową... :]

Za Horyzontem 2005-02-09 22:37

Hmm... może dlatego, że nie mam wersji personal :)
Jesli w >File< >new< nie masz do wyboru >Service Application< to tak nie da się tego zrobić, co nie znaczy że wcale - pomyślę w "wolnej chwili"

milyges 2005-02-03 18:14

Dlaczego nie piszesz że to nie działa w wersji Personal tylko w Enterprise.