Katedra Architektury Systemów Komputerowych Wydział Elektroniki, Telekomunikacji i Informatyki Politechniki Gdańskiej

Podobne dokumenty
Narzędzia i aplikacje Java EE. Usługi sieciowe Paweł Czarnul pczarnul@eti.pg.gda.pl

Katedra Architektury Systemów Komputerowych Wydział Elektroniki, Telekomunikacji i Informatyki Politechniki Gdańskiej

Obiektowe programowanie rozproszone Java RMI. Krzysztof Banaś Systemy rozproszone 1

Kurs programowania. Wykład 8. Wojciech Macyna

Aplikacje RMI

Kurs programowania. Wykład 8. Wojciech Macyna. 10 maj 2017

Wątek - definicja. Wykorzystanie kilku rdzeni procesora jednocześnie Zrównoleglenie obliczeń Jednoczesna obsługa ekranu i procesu obliczeniowego

Obliczenia równoległe i rozproszone w JAVIE. Michał Kozłowski 30 listopada 2003

1 Wątki 1. 2 Tworzenie wątków 1. 3 Synchronizacja 3. 4 Dodatki 3. 5 Algorytmy sortowania 4

Systemy Rozproszone - Ćwiczenie 6

Architektury Usług Internetowych. Laboratorium 2. Usługi sieciowe

Autor: dr inż. Zofia Kruczkiewicz, Programowanie aplikacji internetowych 1

Wątki. Definiowanie wątków jako klas potomnych Thread. Nadpisanie metody run().

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1

Podejście obiektowe do budowy systemów rozproszonych

Metody Metody, parametry, zwracanie wartości

Wywoływanie metod zdalnych

Współbieżność w środowisku Java

Aplikacje RMI Lab4

Remote Method Invocation 17 listopada 2010

Aplikacja Sieciowa wątki po stronie klienta

Wywoływanie metod zdalnych

Java. Wykład. Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ

Programowanie zespołowe

Architektury systemów rozproszonych LABORATORIUM. Ćwiczenie 1

Zaawansowane aplikacje WWW - laboratorium

Remote Method Invocation 17 listopada Dariusz Wawrzyniak (IIPP) 1

Stworzenie klasy nie jest równoznaczne z wykorzystaniem wielowątkowości. Uzyskuje się ją dopiero poprzez inicjalizację wątku.

Wykład 4: Klasy i Metody

Programowanie obiektowe

Programowanie w języku Java - Wyjątki, obsługa wyjątków, generowanie wyjątków

Programowanie obiektowe

Git, Bitbucket, IntelliJ IDEA

D:\DYDAKTYKA\ZAI_BIS\_Ćwiczenia_wzorce\04\04_poprawiony.doc 2009-lis-23, 17:44

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Zdalne wywołanie metod - koncepcja. Oprogramowanie systemów równoległych i rozproszonych Wykład 7. Rodzaje obiektów. Odniesienie do obiektu

Wdrożenie modułu płatności eservice. dla systemu Zen Cart

Podejście obiektowe do budowy systemów rozproszonych

Java RMI. Dariusz Wawrzyniak 1. Podejście obiektowe do budowy systemów rozproszonych. obiekt. interfejs. kliencka. sieć

Oprogramowanie systemów równoległych i rozproszonych Wykład 7

Ćwiczenie 1. Kolejki IBM Message Queue (MQ)

Wielowątkowość. Programowanie w środowisku rozproszonym. Wykład 1.

Aplikacje internetowe i rozproszone - laboratorium

Remote Method Invocation 17 listopada rozproszonych. Dariusz Wawrzyniak (IIPP) 1

Ćwiczenie 1. Przygotowanie środowiska JAVA

Akademia Techniczno-Humanistyczna w Bielsku-Białej

Wdrożenie modułu płatności eservice. dla systemu oscommerce 2.3.x

Komponenty sterowane komunikatami

akademia androida Składowanie danych część VI

1. Co można powiedzieć o poniższym kodzie? public interface I { void m1() {}; static public void m2() {}; void abstract m3();

Co to jest NODE.JS? Nowoczesne środowisko programistyczne

Pobieranie komunikatów GIF

1. Co można powiedzieć o poniższym kodzie (zakładając, że zaimportowano wszystkie niezbędne klasy)?

Interfejsy w Java. Przetwarzanie równoległe. Wątki.

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

akademia androida Service, BroadcastReceiver, ContentProvider część IV

Marcin Luckner Politechnika Warszawska Wydział Matematyki i Nauk Informacyjnych

Wykład 8: Obsługa Wyjątków

Lista dwukierunkowa - przykład implementacji destruktorów

Klasy abstrakcyjne i interfejsy

Rozdział 4 KLASY, OBIEKTY, METODY

Tworzenie i wykorzystanie usług

Język Java wątki (streszczenie)

PHP 5 język obiektowy

Generatory. Michał R. Przybyłek

Wdrożenie modułu płatności eservice. dla systemu Magento

Aplikacje RMI. Budowa aplikacji rozproszonych. Część 2.

WSNHiD, Programowanie 2 Lab. 2 Język Java struktura programu, dziedziczenie, abstrakcja, polimorfizm, interfejsy

Instrukcja tworzenia aplikacji EE na bazie aplikacji prezentowanej na zajęciach lab.4 z PIO umożliwiająca przez sieć dostęp wielu użytkownikom.

Interfejsy. Programowanie obiektowe. Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej

Java RMI. Dariusz Wawrzyniak 1. Podejście obiektowe do budowy systemów rozproszonych. obiekt. interfejs. kliencka. sieć

Wybieramy File->New->Project Wybieramy aplikację MFC->MFC Application jak na rysunku poniżej:

Mechanizmy pracy równoległej. Jarosław Kuchta

EXSO-CORE - specyfikacja

Podstawy tworzenia aplikacji z wykorzystaniem języka Java ME ćwiczenia 2

Jak zainstalować i skonfigurować komunikator MIRANDA, aby wyglądał i funkcjonował jak Gadu Gadu Tutorial by t800.

Przetwarzanie równoległe i współbieżne

Programowanie usług działających w tle

KLASY, INTERFEJSY, ITP

Wyzwalacze. do automatycznego generowania wartości kluczy głównych. Składnia instrukcji tworzacej wyzwalacz

Przykłady interfejsu TCP i UDP w Javie

Cele. Definiowanie wyzwalaczy

Programowanie obiektowe

Podręcznik użytkownika

Dokumentacja wstępna TIN. Rozproszone repozytorium oparte o WebDAV

1. Czynności przygotowujące aplikację działającą na platformie Java SE Biblioteka5 (należy ją pobrać z załącznika z p.1)

Programowanie obiektowe i zdarzeniowe wykład 4 Kompozycja, kolekcje, wiązanie danych

Ciekawym rozwiązaniem służącym do obsługi zdarzeń dla kilku przycisków w ramach jednej aktywności może być następujący kod:

Zaawansowane aplikacje internetowe

AXIS2 - tworzenie usługi sieciowej i klienta Axis Data Binding. dr inż. Juliusz Mikoda mgr inż. Anna Wawszczak

Języki i Techniki Programowania II. Wykład 7. Współbieżność 1

INTERNETOWE BAZY DANYCH materiały pomocnicze - wykład X

Wprowadzenie do laboratorium. Zasady obowiązujące na zajęciach. Wprowadzenie do narzędzi wykorzystywanych podczas laboratorium.

Lekcja 5. Funkcje handlemessage() i initialize(), konstruktor i destruktor

Aplikacja wielowątkowa prosty komunikator

Programowanie obiektowe

SYSTEM MONITORINGU PARAMETRÓW WĘZŁÓW PRZECHOWYWANIA DANYCH DLA PROJEKTU KRAJOWY MAGAZYN DANYCH PODRĘCZNIK DEWELOPERA

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

WPROWADZENIE DO JĘZYKA JAVA

KRYPTOGRAFIA I OCHRONA DANYCH PROJEKT

Transkrypt:

Katedra Architektury Systemów Komputerowych Wydział Elektroniki, Telekomunikacji i Informatyki Politechniki Gdańskiej dr inż. Paweł Czarnul pczarnul@eti.pg.gda.pl Integracja usług w Internecie LABORATORIUM 6 POWIADOMIENIA ORAZ ZARZĄDZANIE ZASOBAMI W GLOBUS TOOLKIT 4 Tematem niniejszego laboratorium są: 1. powiadomienia (ang. notifications) o zmianach w zasobach tj. klient może zostać asynchronicznie powiadomiony o zmianach w zasobie np. zmianie wartości pola typu int, co więcej może (po uprzednim ustawieniu odpowiedniego parametru) odczytać z powiadomienia zarówno poprzednią jak i nową wartość takiego pola. Powiadomienia stanowią znaczne ułatwienie dla programisty jak również zwiększają wydajność i oszczędzają przepustowość łącza komunikacyjnego. Wynika to z faktu, iż alternatywne rozwiązanie odpytywanie zasobu o zmiany (ang. polling) powoduje konieczność: okresowego wysyłania zapytań do serwera powstaje kwestia okresu zbyt krótki spowoduje znaczne obciążenie sieci zaś zbyt długi znaczne opóźnienie w propagacji informacji o zmianie w zasobie w konsekwencji zapewne spadek wydajności, zakodowania logiki odpytującej serwer. Mechanizm powiadomień umożliwia zaś dokonanie subskrypcji informacji o zasobie i jedynie implementację metody wywoływanej po stronie klienta po wystąpieniu zmiany na serwerze. 1. zarządzanie zasobami klient może nie tylko tworzyć zasoby jak pokazano we wcześniejszych laboratoriach, ma również możliwość ich niszczenia, w szczególności w dwóch trybach: natychmiastowym (ang. immediate destruction) zasób jest niszczony natychmiast po wywołaniu metody, z opóźnieniem (ang. scheduled destruction) zasób jest niszczony po upływie zadanego czasu. Ze względu na znakomite przykłady dostarczone z tutorialem Globus Toolkit 4, również dotyczącymi powiadomień i zarządzania zasobami, niniejsze opracowanie rozważy problem, do rozwiązania którego wykorzystany zostanie jedynie mechanizm powiadomień. Ze względu na prostotę mechanizmu niszczenia zasobów, autor odwołuje Czytelnika do przykładów dostarczonych z ww. tutorialem. Znajdują się one pod adresem: Rozważa się następujący problem: Zaimplementować zlecanie zadań przez klienta serwerowi w taki sposób, aby klient zlecał nowe zadania gdy serwer zakończy zadanie(a) zlecone poprzednio. Zakłada się, iż wykonanie zadań może

zająć różną ilość czasu, co więcej czas ten może być znaczący. Zakładając dostępność mechanizmu powiadomień, wydaje się, iż problem ten rozwiązać można stosunkowo prosto tj.: 1. Serwer wykonuje zadanie po czym zmienia stan zasobu, na który klient wcześniej dokonał subskrypcji. 2. Zmiana stanu zasobu powoduje przesłanie powiadomienia do klienta, w rzeczywistości powoduje wywołanie odpowiedniej metody. 3. Klient w ww. metodzie wywołuje po raz kolejny metodę zlecającą serwerowi wykonanie kolejnego zadania. Jest to tym bardziej ułatwione, iż odpowiedni EPR jest dostępny w ww. metodzie. Powyższe rozwiązanie, choć funkcjonalnie bez zarzutu, może zostać ulepszone ze względu na wydajność. Otóż pomiędzy momentem zakończenia wykonywania zadania a momentem rozpoczęcia wykonywania kolejnego zadania upływa czas (powiadomienie, decyzja klienta o uruchomieniu nowego zadania, przesłanie danych) znaczący w przypadku rozważanej technologii. Kod prezentowany poniżej rozwiązuje ten problem w jeden z możliwych sposobów tj.: 1. Po stronie serwera tworzone są dwa wątki wykonujące zadania, podobnie do rozwiązania w instrukcji do laboratorium nr 4. Każdemu z wątków przypisane jest pole zasobu (typu int). Wątek otrzymuje zadanie do wykonania, gdy nie ma zadania, wywołuje metodę wait() przechodząc w stan oczekiwania. w momencie wywołania metody zlecenia zadania, serwer wybiera wolny wątek i zleca mu wykonanie zadania, wątek po wykonaniu zadania modyfikuje przypisane mu określone pole zasobu; powoduje to przesłanie informacji o zmianie stanu zasobu do klienta, który wcześniej dokonał subskrypcji na dany zasób w rzeczywistości uruchamiane są dwa programy klientów, którzy odpowiednio czekają na zmiany ww. dwóch pól (innymi słowy zakończenie wykonania zadania przez dwa wątki). Kod po stronie serwera definiuje pola zasobu wykorzystywane odpowiednio przez pierwszy i drugi wątek: /* Resource properties */ private ResourceProperty valuerp; private ResourceProperty value1rp; Są one inicjalizowane jak w przykładach w poprzedzających instrukcjach. Ponadto, usługa musi implementować interfejs TopicListAccessor, dodatkowo zawiera: /* Topic list */ private TopicList topiclist; /* Configure the Topics */

this.topiclist = new SimpleTopicList(this); valuerp = new ResourcePropertyTopic(valueRP); ((ResourcePropertyTopic) valuerp).setsendoldvalue(true); value1rp = new ResourcePropertyTopic(value1RP); ((ResourcePropertyTopic) value1rp).setsendoldvalue(true); this.topiclist.addtopic((topic) valuerp); this.topiclist.addtopic((topic) value1rp); Umożliwia to klientowi subskrypcję zmian ww. pól. Dodatkowo wywołanie metody setsendoldvalue(true); powoduje, iż klient będzie w stanie pobrać zarówno nową wartość i jak i ustawioną poprzednio. Kod serwera implementuje w inny sposób metodę add(int). Autor zakłada tutaj, iż metoda ta powinna przpisać dane wejściowe (w tym przypadku liczbę typu int) do wolnego wątku i zwrócić sterowanie. W rzeczywistości metoda add(int) zakodowana jest w następujący sposób: public AddResponse add(int a) throws RemoteException { assigndatatothread(a); return new AddResponse(); zaś metoda przydzielająca wątek do danych wejściowych: synchronized private void assigndatatothread(int a) throws RemoteException { for (int i=0; i<computethread.length; i++){ if ( computethread[i].iswaitingfornewrequests()) { // now assign the value to the resource if (i==0) { computethread[i].performcomputation(valuerp,a); System.out.println("starting thread 0 with"+a); else if (i==1) { computethread[i].performcomputation(value1rp,a); System.out.println("starting thread 1 with"+a);

return; throw new RemoteException("No worker thread available"); Metoda performcomputation(...) przyjmuje dane wejściowe oraz pola zasobu, które będą ustawiane po zakończeniu operacji na danych. Faktyczne operacje na danych będą zakodowane w wątku obliczeniowym, który może np. sprawdzać czy dana liczba jest pierwsza czy też nie. Konkretnie, kod wątku obliczeniowego ComputeThread jest analogiczny do wątków całkujących z poprzedniego laboratorium. Po zakończeniu obliczeń zmienia wartość pola zasobu co powoduje powiadomienie klienta: valuerp.set(0,new Integer(data)); Początkowo wartości ww. pól ustawione są na 0. Po zakończeniu pierwszych wywołań (jak opisano poniżej) wartości ustawione są na argumenty podane w wywołaniu klienta z linii poleceń, w kolejnych wywołaniach generowanych już automatycznie po otrzymaniu powiadomienia, iż wątek jest bezczynny wartości te ustawiane są na kolejne liczby naturalne. Oczywiście, wynik obliczeń może być ustawiany jw. 1. Kod, analogicznie do przykładu dotyczącego powiadomień w tutorialu Globus Toolkit 4, składa się z dwóch klas: klient wywołujący metodę zlecającą jedno zadanie, klient nasłuchujący na zmianę zasobu (klient nasłuchuje na zmianę pola typu int przypisanego do pierwszego wątku patrz wyżej); po otrzymaniu informacji o zmianie zasobu (innymi słowy zakończeniu zadania przez pierwszy wątek) metoda ta zleca wykonanie kolejnego zadania. Kompilacja źródeł aplikacji po stronie serwera (w katalogu, który powstanie po rozpakowaniu archiwum): globus@wolf:~/ti lab 6$./globus build service.sh notifications Wdrożenie aplikacji: globus@wolf:~/ti lab 6$ globus deploy gar org_globus_examples_services_core_notifications.gar

Uruchomienie serwera: globus@wolf:~/ti lab 6$ globus start container nosec Następnie należy skompilować źródła trzech klientów: globus@wolf:~/ti lab 6$ javac org/globus/examples/clients/mathservice_instance_notif/valuelistener.java globus@wolf:~/ti lab 6$ javac org/globus/examples/clients/mathservice_instance_notif/valuelistener1.java globus@wolf:~/ti lab 6$ javac org/globus/examples/clients/mathservice_instance_notif/clientadd.java Następnie należy uruchomić programy klientów (w osobnych konsolach, w podanej kolejności): 1. globus@wolf:~/ti lab 6$ java DGLOBUS_LOCATION=$GLOBUS_LOCATION classpath./build/stubs/classes/:$classpath org/globus/examples/clients/mathservice_instance_notif/valuelistener http://127.0.0.1:8080/wsrf/services/examples/core/notifications/mathservice Waiting for notification. Ctrl C to end. 2. globus@wolf:~/ti lab 6$ java DGLOBUS_LOCATION=$GLOBUS_LOCATION classpath./build/stubs/classes/:$classpath org/globus/examples/clients/mathservice_instance_notif/valuelistener1 http://127.0.0.1:8080/wsrf/services/examples/core/notifications/mathservice Waiting for notification. Ctrl C to end. 3. Po uruchomieniu klientów nasłuchujących, należy uruchomić klienta, który zleci zadanie do wykonania najpierw pierwszemu a następnie drugiemu wątkowi (wątki zostaną przypisane automatycznie przez metodę po stronie serwera). Argumentem wywołania jest liczba typu int, która jest przekazywana do każdego wątku. globus@wolf:~/ti lab 6$ java classpath./build/stubs/classes/:$classpath org/globus/examples/clients/mathservice_instance_notif/clientadd http://127.0.0.1:8080/wsrf/services/examples/core/notifications/mathservice 1000 Value RP: 0 LastOp RP: NONE należy odczekać kilka sekund i: globus@wolf:~/ti lab 6$ java classpath./build/stubs/classes/:$classpath org/globus/examples/clients/mathservice_instance_notif/clientadd http://127.0.0.1:8080/wsrf/services/examples/core/notifications/mathservice 2000

Value RP: 0 LastOp RP: NONE globus@wolf:~/ti lab 6$ Wywołania powinny zwrócić sterowanie od razu, zaś wątki rozpoczną pracę, co zostanie udokumentowane komunikatami po stronie serwera: starting thread 0 with1000 Thread[Thread 0,5,main].starting computations starting thread 1 with2000 Thread[Thread 1,5,main].starting computations Thread[Thread 0,5,main].***1000*0 Następne zadania będą już zlecane automatycznie poprzez klientów nasłuchujących (ValueListener oraz ValueListener1) tj. po wykonaniu zadania przez jeden wątek, jeden z klientów zostanie powiadomiony i prześle kolejne zadanie (w tym czasie drugi z wątków po stronie serwera będzie zajęty). To samo tyczy się drugiego wątku. Zakończenie kolejnych zadań spowoduje uruchomienie nowych itd. Komunikaty widoczne po stronie klientów nasłuchujących będą miały postać: globus@wolf:~/ti lab 6$ java DGLOBUS_LOCATION=$GLOBUS_LOCATION classpath./build/stubs/classes/:$classpath org/globus/examples/clients/mathservice_instance_notif/valuelistener1 http://127.0.0.1:8080/wsrf/services/examples/core/notifications/mathservice Waiting for notification. Ctrl C to end. Old value: 0 New value: 2000 Old value: 2000 New value: 2001 Old value: 2001 New value: 2002 Old value: 2002 New value: 2003 i dla drugiego klienta: globus@wolf:~/ti lab 6$ java DGLOBUS_LOCATION=$GLOBUS_LOCATION classpath./build/stubs/classes/:$classpath org/globus/examples/clients/mathservice_instance_notif/valuelistener

http://127.0.0.1:8080/wsrf/services/examples/core/notifications/mathservice Waiting for notification. Ctrl C to end. Old value: 0 New value: 1000 Old value: 1000 New value: 1001 Old value: 1001 New value: 1002 Old value: 1002 New value: 1003 Wynika to z faktu, iż klient nasłuchujący odczytuje nową wartość zmienionego zasobu, dodaje 1 i wywołuje ponownie metodę po stronie serwera: public class ValueListener implements NotifyCallback { /* This method is called when a notification is delivered */ public void deliver(list topicpath, EndpointReferenceType producer, Object message) { ResourcePropertyValueChangeNotificationElementType notif_elem; ResourcePropertyValueChangeNotificationType notif; notif_elem = (ResourcePropertyValueChangeNotificationElementType) message; notif = notif_elem.getresourcepropertyvaluechangenotification(); MathServiceAddressingLocator instancelocator = new MathServiceAddressingLocator(); if (notif!= null) { System.out.println(""); System.out.print("Old value: "); System.out.println(notif.getOldValue().get_any()[0].getValue()); System.out.print("New value: "); System.out.println(notif.getNewValue().get_any()[0].getValue()); try { MathPortType math = instancelocator.getmathporttypeport(producer);

+1); // Perform addition math.add(integer.valueof(notif.getnewvalue().get_any()[0].getvalue()).intvalue() catch (Exception e) { System.out.println("Error"); e.printstacktrace();... Pomimo tego, iż implementacja osiągnęła cele wymienione powyżej, w rzeczywistości idea polega na uruchomieniu dwóch klientów (drugi z pewnym opóźnieniem), z których każdy jest powiadamiany o dostępności jego wątku i ponownie zleca mu zadanie. Uruchomienie z opóźnieniem powoduje, iż serwer jest zajęty obliczeniami drugiego wątku, gdy pierwszy przesyła kolejne dane (i odwrotnie). Autor pozostawia poniższe kwestie do analizy Czytelnikowi co powinno dalej poprawić kod tj.: 1. Dotychczasowa implementacja wykorzystuje różne kody klientów. 2. Serwer wykorzystuje dwa wątki do obliczeń. Alternatywą byłoby wykorzystanie tylko jednego wątku do obliczeń oraz umożliwienie klientowi umieszczenia nowych danych po stronie serwera w czasie gdy wątek przetwarza wcześniej zapisane dane. Wątek, po przetworzeniu danych, pobiera kolejne, które już znajdują się po stronie serwera. Tego typu techniki opisane są również w kontekście aplikacji mobilnych w technologii J2ME. Autor odsyła Czytelnika do artykułu dostępnego pod adresem: http://developers.sun.com/techtopics/mobility/ midp/articles/threading/.