Architektur Verteilter Systeme Hinweise zu den Aufgabenblättern Teil 1 19.04.17 1
Etwas zur Wiederholung bzw. Vertiefung [1] Webtechnologien (2. Semester) HTTP Entwicklungsumgebungen PHP Teil 1 bis 3 Javascript Teil1 und besonders Teil4 (Ajax-Routine) [2] Rechnernetze (1. Semester) OSI-Modell http://wi.f4.htw-berlin.de/users/messer/lv/wi-avs-ws16/index.html 2
Allgemeines I Web-Ressource Web-Ressource = PHP-Skript mit URL als Name Auf eine Web-Ressource wird mit der GET-Methode zum Lesen und (hier) mit der POST-Methode zum Schreiben zugegriffen. Vereinfachend kann aber auch immer mit POST gearbeitet werden. Die zugreifende Software kann ein Browser oder ein Server sein. URL Server PHP- Skript 3
Allgemeines II URL Browser Browser Verkürzte Darstellung (1) (4) (3) Server PHP- Skript (2) Server In vier Schritten verläuft der Zugriff auf Web-Ressourcen. Der Client stößt den Vorgang an: pull-verfahren (Ziehen) Der Server kann hier nur darauf warten, dass er befragt wird; er kann keine Informationen von sich an den Client senden. Zum Start muss in den Client per URL (in der Adress-Leiste) die Seite samt Javascript-Code geladen werden, damit Schritt (1) ausgeführt wird. PHP- Skript Es gibt einen Mechanismus, wo der Server den Browser anstoßen kann; dies wird nicht hier behandelt. 4
Allgemeines III - Aufbau der URL http://www.meinelieblingssite.de/dateiname?key1=val1&key2=val2&... Adresse des Servers Skriptname Skriptparameter Dateiname(key1=val1, key2=val2,,keyn=valn) Dies hier basiert auf der HTTP-Get-Methode. Mit POST geht es auch, nur dass der String hinter dem? im Body des HTTP-Paketes sich befindet. 5
Allgemeines IV Beispiel für die GET-Methode http://141.45.20.30/login.php?id=elvira&pw=12345 login(elvira,12345) Zugriff in login.php: $_GET['id'] $_GET['pw'] Statt eines DNS-Namens kann auch die IP-Adresse angegeben werden. Der Dateiname wird hier als Name einer Routine aufgefasst. Da in dieser LV fast immer mit der POST-Methode gearbeitet wird, erfolgt der Zugriff auf die Werte per $_POST['id'] bzw. $_POST['pw']. 6
Woher kennen sich die Server? I Browser Server1 Browser Server2 Anmelden Abfragen Repository Browser ServerN Im ersten Aufgabenblatt wird ein Repository realisiert. Mit der eigenen IP-Adresse und dem eigenen Namen melden sich die Server 1 bis N dort an. Alle Server können dann von einander erfahren. Bitte beachten Sie, dass alles parallel abläuft; daher wissen die Server nicht, ob alle Server sich schon angemeldet haben. 7
Woher kennen sich die Server? II Wie erfährt ein Server, wer er selbst ist? Die eigene IP-Adresse steht in $_SERVER['SERVER_ADDR']. Damit kann er sich beim Repository anmelden. Wie erfährt ein Server, von wem er den Request erhielt? Diese Adresse steht in $_SERVER['REMOTE_ADDR'], sofern kein Proxy- Server dazwischen geschaltet ist. Falls doch: if (isset($_server['http_x_forwarded_for'])) { $cip= $_SERVER['HTTP_X_FORWARDED_FOR']; } else { $cip= $_SERVER['REMOTE_ADDR']; } Siehe http://php.net/manual/de/reserved.variables.server.php 8
Wie kommen die Quellen auf die Server? I Rechner1 Browser Entwicklungsrechner Server1 Rechner2 htdocs kopieren Browser Server2 Auf einem der Rechner (Rechner1) wird entwickelt und dort lokal auf htdocs installiert. Vor dem Lauf werden alle Dateien aus htdocs von Rechner1 auf den zweiten und weiteren Rechner etc. kopiert. 9
Wie kommen die Quellen auf die Server? II Feststellen der Identität - Idee Alle Dateien einer Lösung werden an einem Rechner erstellt. Dann werden sie auf alle anderen Rechner verteilt. Zum Start wird jedem Server bis auf das Repository per URL- Aufruf seine Identität, d.h. seinen symbolischen Namen, mitgeteilt. Beispiel http://141.45.10.12/boot.php?id=hansi&repo=141.45.10.15&... mit id wird der Name und mit repo die IP-Adresse des Repository definiert. Die beiden Parameter id und repo müssen natürlich in der Routine boot.php ausgewertet und vermerkt werden. In der Routine boot.php melden sich dann alle Server beim Repository an und erfahren von dort, wer alles zur ihrer Gruppe gehört. Dann beginnt der eigentliche Teil des Skripts. 10
Wie kommen die Quellen auf die Server? III Feststellen der Identität - Alternative Idee Rechner1 Browser Server1 include Liste der IP-Adressen mit Namen Rechner2 Browser Server2 Die Liste der IP-Adressen wird manuell vor dem Lauf bestimmt. Diese wird den Servern per include in die PHP-Skripte mitgeteilt. Die Browser können anhand ihrer IP-Adressen und der Liste feststellen, wie sie heißen, und sich beim Repository anmelden. 11
Wie kommen die Quellen auf die Server? IV Liste der IP-Adressen mit Namen Aufbau der IP-Liste $IP_List[]= array('name'=>'name1', 'IP'=>'IP1'); $IP_List[]= array('name='>'name2', 'IP'=>'IP2');... $IP_List[]= array('name'=>'namen', 'IP'=>'IPN'); Jeder Server hat einen Namen Name1...NameN und auch eine IP- Adresse als String in der Punktnotation, also z.b. 141.45.1.1. Ein Eintrag betrifft das das Repository. In gewisser Hinsicht wäre dies ein Ersatz des Repository, eine Art Fallback. 12
Wie kommen die Quellen auf die Server? V Möglichkeiten der Installation Es wird mit einem Memory-Stick kopiert: einfach und aufwändig. Wenn alle VMs auf einem Rechner liegen, kann mit einem Shared Folder gearbeitet werden: Dies geht nur unter root innerhalb der VM. Am besten ist es, wenn Sie sich ein Shell-Skript zum Kopieren schreiben, das Sie vor jedem Lauf aufrufen. Da in jeder VM ein FTP-Server installiert ist, können Sie diesen nehmen: Sie benötigen einen Client, der in der VM noch installiert werden muss. Sie müssen den FTP-Server konfigurieren und er muss mit Passwörtern arbeiten. Sie müssen die FTP-Ports auf dem verteilenden Server auf dem Entwicklungssystem öffnen. 13
Die Sache mit der Firewall I Rechner1 Rechner2 Browser Web- Server Firewall Port 80 Firewall Web- Server Um von Außen einen HTTP-Request empfangen zu können, muss beim Empfänger die Firewall den Port 80 öffnen. Dasselbe ist bei einem FTP-Server nötig. In der Richtung von Innen nach Außen ist die Firewall immer offen, nur umgekehrt nicht (jedenfalls normalerweise). 14
Die Sache mit der Firewall II Als root einloggen (id=root, pw=rootroot) Über System>Administration>Firewall die Konfiguration anstoßen. 15
Die Sache mit der Firewall III Ein Häkchen bei WWW (HTTP) machen und vielleicht das Häkchen bei SSH darüber wegmachen. Dann oben auf Anwenden klicken und bestätigen. 16
Die Sache mit der Firewall IV Dann den Webserver starten (falls es nicht schon vorher erfolgte). Im Shell mit dem ifconfig-kommando die eigene IP-Adresse bestimmen. Das wird dann mit allen beteiligten VMs gemacht. Die IP-Adressen werden in die include-datei geschrieben (siehe oben). 17
Die Sache mit der Firewall V Es ist hoffentlich klar, dass mit offenen Ports nur in einer sicheren Umgebung gearbeitet werden sollte! Auf einer anderen Maschine im Shell mit nmap die offenen Ports bestimmen: es muss Port 80 offen sein. 18
Wechselseitiger Ausschluss I Browser1 Server Hier wird der Apache als Server angenommen. Browser2 Nicht nur mehrere Browser können parallele Aktivitäten auslösen, sondern auch ein Browser kann mehrere Skripte parallel starten (mittels Ajax). PHP- Skript1 Thread1 PHP- Skript2 Thread2 Jedes Skript läuft in einem eigenen Thread parallel zu anderen Skripten. Wechselseitiger Ausschluss ist für den Zugriff auf Dateien daher erforderlich. 19
Wechselseitiger Ausschluss II Bemerkung In XAMPP wird die nicht-thread-fähige PHP-Implementierung benutzt. Dies bezieht sich jedoch auf die fehlende Möglichkeit Threads innerhalb eines Skripts zu benutzen. Hier wird aber der Zugriff von mehreren gleichzeitig laufenden PHP-Skripten (ohne Threads innerhalb PHP) auf die gemeinsam verwendeten Dateien thematisiert. Siehe dazu: http://stackoverflow.com/questions/1430883/simultaneousrequests-to-php-script 20
Wechselseitiger Ausschluss III Klasse Es wird die Klasse Semaphore implementiert. Dazu gibt es mehrere Möglichkeiten: Mit den Unix-Semaphoren (wurde nicht besprochen): https://php.net/manual/de/function.sem-get.php Diese beginnen mit sem_ Über eine Datei mit flock (wurde nicht besprochen): http://php.net/manual/de/function.flock.php Dies ist eigentlich die beste Lösung Über das Anlegen und Löschen einer Datei. Ist sie vorhanden: Sperre, ist sie nicht vorhanden: Offen. Diese Lösung ist sehr einfach, aber leider nicht ganz korrekt, denn unter sehr unwahrscheinlichen Bedingungen gibt es Probleme. Diese einfache Lösung wird für die Aufgaben in dieser Lehrveranstaltung empfohlen. 21
Server-Server Kommunikation I Dazu benötigen Sie eine Server-Server-Kommunikation in PHP; dazu gibt es mehrere Möglichkeiten: Das pecl-http-paket http://php.net/manual/de/httprequest.send.php in der VM nicht installiert Das PEAR-Paket HTTP_Request2 ist installiert. https://pear.php.net/package/http_request2 Das curl-paket ist installiert. Etwas schwer zu konfiguieren. Das Paket httpful in der VM im PHP-Ordner vorhanden. http://phphttpclient.com/ https://github.com/nategood/httpful Dieses Paket ist eine Art Wrapper um curl herum und vereinfacht dessen Benutzung. 22
Server-Server Kommunikation II Server: Beispiel PEAR-Paket require 'HTTP/Request2.php'; $request = new HTTP_Request2('http://pear.php.net/bugs/search.php', HTTP_Request2::METHOD_GET, array('use_brackets' => true)); $url = $request->geturl(); $url->setqueryvariables(array( 'package_name' => array('http_request2', 'Net_URL2'), 'status' => 'Open' )); $url->setqueryvariable('cmd', 'display'); // This will output a page with open bugs for Net_URL2 and HTTP_Request2 echo $request->send()->getbody(); [Von der PEAR-Site] 23
Server-Server Kommunikation III Zum Austausch der Informationen werden folgende Formate benutzt: Hinweg: URL-Encoding mit GET/POST Rückweg: JSON Hinweg und Rückweg: JSON Es gibt ein Beispiel-Projekt mit Ajax, das entsprechend der ersten Variante funktioniert. Siehe dazu: http://php.net/manual/de/jsonserializable.jsonserialize.php http://php.net/manual/de/book.json.php https://de.wikipedia.org/wiki/url-encoding 24
Kommunikation möglichst mit JSON Browser URL JSON Server JSON JSON Server Browser JSON JSON Server Diese Variante geht nur, wenn im Browser mit Ajax gearbeitet wird. Beispiel für eine JSON-Nachricht: { "Message" : "das ist eine Nachricht", "Sender" : "Iris", "More" : 0 } 25
Ausgabe in JavaScript I Sie können das Objekt console.log benutzen. Die Benutzung ("Hauptprogramm"): <script type="text/javascript"> console.log("das ist eine Ausgabe in die Console des Browsers"); </script> Mit Firebug sieht das dann so aus: 26
Ausgabe in JavaScript II Oder die einfache Implementierung aus Webtechnologien. Die Benutzung ( Hauptprogramm"): <script type="text/javascript" src="js/writer.js"></script> <script type="text/javascript"> write2console("das ist das Consolen-Fenster"); </script> Das sieht dann so aus: 27
Ajax-Kommunikation I Ein Vorschlag Sie können jquery benutzen (oder ein anderes Framework) oder Sie benutzen das kleine Ajax-Projekt (Homepage des Dozenten) Die Benutzung ( Hauptprogramm"): (01) <script type="text/javascript" src="js/ajax.js"></script> (02) <script type="text/javascript" src="js/writer.js"></script> (03) <script type="text/javascript"> (04) var URL = "http://localhost/ajax-console/getdate.php"; (05) var ajaxcom= new Ajax(URL,receive); (06) receivedobj= {"date": 0}; (07) ajaxcom.send({"msg": "Heute ist "}); (08) write2console(receivedobj.date); (09) ajaxcom.disconnect(); (10) </script> 28
Ajax-Kommunikation II Erläuterungen Zeile 4: Die URL für den Ajax-Request. Zeile 5: Das Ajax-Objekt wird angelegt: 1. Parameter: URL als String 2. Parameter: Name einer Callback-Routine Diese Callback-Routine receive() wird beim Empfang aufgerufen und legt ein globales Objekt Namens receivedobj an. Zeile 6: Es wird der Variablen receivedobj ein JSON-Objekt mit den erwarteten Komponenten zugewiesen. Zeile 7: Der Request wird als POST gesendet, wobei ein JSON-Objekt mit den Parametern übergeben wird. (04) var URL = "http://localhost/ajax-console/getdate.php"; (05) var ajaxcom= new Ajax(URL,receive); (06) receivedobj= {"date": 0}; (07) ajaxcom.send({"msg": "Heute ist "}); (08) write2console(receivedobj.date); 29
Ajax-Kommunikation III Erläuterungen Zeile 8: Die Antwort ist empfangen und liegt im Objekt receivedobj vor, wobei dort nur die Komponenten definiert sind, die vor dem Request als JSON-Objekt definiert wurden (Zeile 6). Zeile 6 ist damit eine Art Filter. Definition der erwarteten (04) var URL = "http://localhost/ajax-console/getdate.php"; Antwort (05) var ajaxcom= new Ajax(URL,receive); (06) receivedobj= {"date": 0}; (07) ajaxcom.send({"msg": "Heute ist "}); (08) write2console(receivedobj.date); Senden und Empfangen mit den POST-Parametern 30
Ajax-Kommunikation IV Erläuterungen Browser URL JSON Server Hinweg: Datenaustausch über POST-Parameter url-encoded Rückweg: Datenaustausch mit einer JSON-Struktur 31
Ajax-Kommunikation V Server-Teil Die Aufgabe des Servers ist hier das Liefern der aktuellen Datums im HTML-Format. Die Kommunikation zum Browser erfolgt mit JSON. Zeile 1 bis 5 ist der übliche Zugriff auf die POST-Parameter. (01) if(isset($_post['msg'])) { (02) $mesg= $_POST['msg']; (03) } else { Daten vom Browser (04) $mesg= 'Now is'; (05) } (06) echo "bla1"; // Simulation einer Fehlermeldung (07) $message= "$mesg <b><i>".strftime("%d.%m.%y %H:%M:%S")."</i></b>"; (08) echo json_encode(array('date'=> $message)); (09) echo "bla2"; // Simulation einer weiteren Fehlermeldung 32
Ajax-Kommunikation V Server-Teil Zeile 7: Hier wird der Inhalt generiert (Datum) Zeile 8: Es wird ein Array/Hash generiert, nach JSON konvertiert und mit echo ausgegeben. Diese Ausgabe geht automatisch an den Browser, der ein JSON-Konstrukt erwartet. Zeile 6 und 9: Hier werden PHP-Fehlermeldungen simuliert, die ja in den Ausgabedatenstrom fließen und nicht konform zu JSON sind. Der Browser versucht den Nicht-JSON-Vorspann und -Nachspann zu extrahieren und auf der Konsole auszugeben (klappt aber nicht immer richtig). (01) if(isset($_post['msg'])) { (02) $mesg= $_POST['msg']; (03) } else { (04) $mesg= 'Now is'; (05) } (06) echo "bla1"; // Simulation einer Fehlermeldung (07) $message= "$mesg <b><i>".strftime("%d.%m.%y %H:%M:%S")."</i></b>"; (08) echo json_encode(array('date'=> $message)); (09) echo "bla2"; // Simulation einer weiteren Fehlermeldung 33
Realisierung I 34
Realisierung II Die Ajax-Anfrage Das ist die Anfrage {"date":"heute ist <b><i>12.04.2016 12:25:50<\/i><\/b>"} Das ist das JSON-Objekt Simulierte Fehlermeldungen Das ist die Antwort 35
Realisierung III - netbeans Die JS-Dateien stehen in einem eigenen Unterordner Dieses netbeans-projekt kann von der Website zu dieser Veranstaltung herunter geladen werden. Der Source-Code des Ajax-Projekts wurde in der letzten Veranstaltung Webtechnologien besprochen: http://wi.f4.htw-berlin.de/users/messer/lv/wi-avs- SS17/Folien/Wiederholung/18-WT-JavaScript-IV-1.pdf Dazu gibt es auch Videos. 36
Realisierung IV - netbeans Es gibt eine Windows und eine Linux-Version, die sich nur durch den Ort für den htdocs-ordner unterscheiden. Dies lässt sich leicht im Properties-Bereich des netbeans-projekts auch nachträglich ändern. Das ist der Ordner für die Windows-Version 37
Nach dieser Anstrengung etwas Entspannung... Dieses Brett ist etwas lose. Über manche Brücken sollten wir nur allein gehen... 38