<?xml version="1.0"?>
<!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">
<?xml-stylesheet type="text/xsl" href="../style/manual.de.xsl"?>
<modulesynopsis metafile="mod_unique_id.xml.meta">

<name>mod_unique_id</name>
<description>Stellt eine Umgebungsvariable mit einer eindeutigen Bezeichnung
f&uuml;r jede Anfrage zur Verf&uuml;gung.</description>
<status>Erweiterung</status>
<sourcefile>mod_unique_id.c</sourcefile>
<identifier>unique_id_module</identifier>

<summary>

    <p>Dieses Modul stellt eine Umgebungsvariable mit einer
    Bezeichnung f&uuml;r jede Anfrage zur Verf&uuml;gung, die unter bestimmten
    Bedingungen f&uuml;r jede Anfrage eindeutig ist. Diese Bezeichnung
    ist auch f&uuml;r unterschiedliche Rechner eines entsprechend konfiguierten
    Cluster eindeutig. Die Umgebungsvariable <code>UNIQUE_ID</code>
    wird f&uuml;r jede Anfrage gesetzt. Eindeutige Bezeichnungen sind f&uuml;r
verschiedene Zwecke n&uuml;tzlich, deren Beschreibung den Rahmen dieses 
Dokuments sprengen w&uuml;rde.</p>
</summary>

<section id="theory">
    <title>Hintergrund</title>

    <p>Beginnen wir mit einer kurzen Zusammenfassung der Funktionsweise des
     Apache-Servers unter Unix funktioniert. (Unter Windows NT wird dieses
     Modul nicht unterst&uuml;tzt.) Auf Unix-Rechnern erzeugt der Apache mehrere
     Kindprozesse, von denen jeder (die ihm zugeteilten) Anforderungen
     nacheinander abarbeitet. Jeder Kindprozess kann
     w&auml;hrend seiner Lebensdauer mehrere Anfragen bedienen. Im Zusammenhang
     dieser Erl&auml;uterung wird davon ausgegangen, dass die Kindprozesse keine
     Daten gemeinsam nutzen. Sie werden als HTTPD-Prozesse bezeichnet.</p>

    <p>Die Website operiert mit einem oder mehreren Rechnern, die in
    ihrer Gesamtheit als Cluster bezeichnet werden. Jeder Rechner kann mehrere
    Apache-Instanzen ausf&uuml;hren, die hier in ihrer Gesamtheit als
    "Universum" bezeichnet werden. Wir werden nachweisen, da&szlig; es unter
    bestimmten Voraussetzungen in diesem Universum m&ouml;glich ist, eindeutige
    Bezeichnungen f&uuml;r jede Anfrage zu erzeugen, ohne dass daf&uuml;r
    eine ausf&uuml;hrlichere Kommunikation zwischen den Rechnern des Clusters
    erforderlich ist.</p>

    <p>Die Rechner des Clusters sollten die folgenden Anforderungen 
erf&uuml;llen
    (selbst wenn nur ein Rechner vorhanden ist, sollte dessen Uhr mit
    NTP synchronisiert werden):</p>

    <ul>
      <li>Die Uhrzeiten der Rechner werden &uuml;ber NTP oder ein anderes
      Netzwerkprotokoll synchronisiert.</li>

      <li>Die Host-Namen aller beteiligten Rechner unterscheiden sich 
voneinander, so
      dass das Modul eine Suche nach Host-Namen durchf&uuml;hren kann und
      f&uuml;r jeden Rechner des Clusters eine andere IP-Adresse 
erh&auml;lt.</li>
    </ul>

    <p>Hinsichtlich des Betriebssystems wird davon ausgegangen, dass die
    Pids (Prozess-IDs) maximal 32 Bit lang sind. Verwendet das Betriebssystem 
mehr als
    32 Bit f&uuml;r eine Pid, dann l&auml;sst sich der Code leicht anpassen.</p>

    <p>Unter diesen Voraussetzungen kann zu einem bestimmten
    Zeitpunkt jeder HTTPD-Prozess eines beliebigen Rechners aus dem
    Cluster von allen anderen HTTPD-Prozessen unterschieden werden. Hierf&uuml;r
    reichen die IP-Adresse des Rechners und die Pid des HTTPD-Prozesses
    aus. Um eindeutige Bezeichnungen f&uuml;r jede Anfrage erzeugen zu 
k&ouml;nnen,
    m&uuml;ssen lediglich die verschiedenen Zeitpunkte unterschieden werden.</p>

    <p>F&uuml;r diese Unterscheidung wird ein Unix-Zeitstempel
    (die seit dem 1. Januar 1970 (UTC) vergangegenen Sekunden) und ein
    16-Bit-Z&auml;hler verwendet. Der Zeitstempel hat nur eine Genauigkeit von
    einer Sekunde, weshalb der Z&auml;hler daf&uuml;r verwendet wird, bis zu 
65.536
    verschiedene Werte pro Sekunde darstellen zu k&ouml;nnen.
    Dieses Quadrupel aus <code>ip_addr</code>,
    <code>pid</code>, <code>time_stamp</code> und Z&auml;hler reicht
    aus, um 65.536 Anfragen pro Sekunde und HTTPD-Prozess zu
    nummerieren. Die Tatsache, dass die Prozess-IDs im Laufe der
    Zeit wiederverwendet werden, wird durch den Z&auml;hler 
ber&uuml;cksichtigt.</p>

    <p>Wird ein HTTPD-Kindprozess erzeugt, dann wird der Z&auml;hler mit
    dem Restwert der Division der (Anzahl der vergangenen Mikrosekunden
    durch 10) dividiert durch 65.536 initialisiert, um Varianzprobleme
    mit den niederwertigen Bits des Mikrosekunden-Zeitgebers einiger
    Systeme zu vermeiden. F&uuml;r das Erzeugen einer eindeutigen Bezeichnung
    wird der Zeitstempel der Eingangszeit der Anfrage beim Webserver benutzt.
    Der Z&auml;hler wird beim Erzeugen einer Bezeichnung immer
    inkrementiert (und darf &uuml;berlaufen).</p>

    <p>Der Betriebssystemkernel erzeugt beim Aufspalten jedes Prozesses eine Pid
    , beider es irgendwann zum &Uuml;berlauf und damit zur Wiederverwendung der
    Pids kommt (bei vielen Unix-Systemen ist sie 16 Bit und bei neueren maximal
    32 Bit lang). Erfolgt diese Wiederverwendung jedoch nicht innerhalb der
    gleichen Sekunde, wird die Eindeutigkeit des Quadrupels nicht gest&ouml;rt. 
Es wird also
    davon ausgegangen, dass das System nicht mehr als 65.536 Prozesse
    pro Sekunde startet (bei einigen Unix-Systemen k&ouml;nnen es zwar bis zu
    32.768 Prozessen sein, was allerdings sehr unwahrscheinlich ist).</p>

    <p>Angenommen, da&szlig; aus irgend einem Grund dieselbe Uhrzeit
ein zweites Mal auftritt. Das hei&szlig;t also, da&szlig; der Stand
der Systemuhr ruiniert wurde und sie einen vergangenen
Zeitpunkt noch einmal durchl&auml;uft (oder da&szlig; sie zu weit
in der Zukunft steht, anschlie&szlig;end auf den korrekten Wert
zur&uuml;ck gesetzt wird und danach den Zeitpunkt in der Zu-
kunft ein zweites Mal erlebt). F&uuml;r diesen Fall l&auml;&szlig;t sich leicht 
nachweisen,
da&szlig; es zu einer Wiederverwendung der Kombination aus Pid
und Uhrzeit kommen kann. Die Wahl des Startwertes f&uuml;r den Z&auml;hler soll
dabei helfen, mit dieser Situation fertig zu werden. Beachten Sie, da&szlig; wir
eigentlich dringend eine echte Zufallszahl verwenden sollten, um diesen 
Z&auml;hler
zu initalisieren, die aber bei den meisten Systemen nicht
zur Verf&uuml;gung steht (insbesondere kann die Funktion <code>rand()</code>
nicht verwendet werden, weil zun&auml;chst einmal deren Generator
initialisiert werden m&uuml;&szlig;te - und genau daf&uuml;r d&uuml;rfen wir die
Uhrzeit nicht verwenden, weil diese sich ja bereits
wiederholt hat). Diese L&ouml;sung ist nicht perfekt.
</p>

<p>Wie gut ist die L&ouml;sung? Angenommen ein Rechner bedient
500 Anfragen pro Sekunde (was eine realistische Obergrenze ist, weil Systeme im
Allgemeinen mehr zu tun haben, als einfach nur den Inhalt statischer Dateien
zu versenden).
Hierf&uuml;r ben&ouml;tigt er eine Reihe von Kindprozessen, deren Zahl von
der Anzahl der konkurrierenden Clients abh&auml;ngt. Aber wir sind mal
pessimistisch und gehen davon aus, dass bereits ein einzelner Prozess in der
Lage w&auml;re, bis zu 500 Anfragen pro Sekunde zu bedienen. Daraus ergeben
sich 1.000 m&ouml;gliche Anfangswerte f&uuml;r den Z&auml;hler, bei denen zwei 
Sequenzen
von je 500 Anfragen einander &uuml;berlappen w&uuml;rden. Bei einer
Zeitwiederholung und einer Zeitaufl&ouml;sung in Sekunden besteht daher eine
Wahrscheinlichkeit von 1,5 % f&uuml;r eine Wiederholung des Z&auml;hlerwertes 
und
f&uuml;r eine Aufhebung der Eindeutigkeit. Dies ist eine sehr pessimistische
Ausgangssituation, die in der Praxis wahrscheinlich nicht eintreten wird.
Falls Ihr System derartig beschaffen ist, dass diese Wahrscheinlich-
keit Ihnen immer noch zu hoch ist, dann sollten Sie m&ouml;glicherweise
den Z&auml;hler auf 32 Bit verl&auml;ngern, indem Sie den Modulquellcode
entsprechend anpassen.</p>

<p>Vielleicht sind Sie jetzt besorgt wegen der 'Zur&uuml;ckstellung' Ihrer
Systemuhr bei der Umschaltung auf Sommerzeit. Dies ist jedoch kein
Problem, weil die hier verwendete Zeit die UTC ist, welche immer
vorw&auml;rts l&auml;uft. Beachten Sie, da&szlig; ein auf x86 basierendes Unix 
eine entsprechende
Konfiguration ben&ouml;tigen kann, um diese Eigenschaften zu garantieren:
Es sollte so konfiguriert sein, da&szlig; es die Uhrzeit seines Motherboards
als UTC interpretiert und entsprechende Umrechnungen dynamisch vor-
nimmt. Aber selbst in diesem Fall wird die UTC-Zeit ziemlich bald nach dem
Neustart wieder korrekt sein, falls Sie NTP verwenden.</p>

    <p>Die Umgebungsvariable <code>UNIQUE_ID</code>  wird durch
    Kodierung des 112 Bit gro&szlig;en Quadrupels (32-Bit-IP-Adresse,
    32-Bit-Pid, 32-Bit-Zeitstempel, 16-Bit-Z&auml;hler) mit Hilfe des Alphabets
    <code>[EMAIL PROTECTED]</code> in einer mit der MIME-base64-Kodierung
    vergleichbaren Form mit 19 Zeichen konstruiert. Das MIME-base64-Alphabet
    umfasst eigentlich die Zeichen <code>[A-Za-z0-9+/]</code>, die Zeichen
    <code>+</code> und <code>/</code> m&uuml;ssen in URLs jedoch speziell
    kodiert werden und sind daher nicht so erw&uuml;nscht. Alle Werte werden
    in der Netzwerk-Bytereihenfolge kodiert, so dass die Kodierung
    bei Architekturen mit unterschiedlicher Bytereihenfolge vergleichbar ist. 
Die
    tats&auml;chliche Reihenfolge der Kodierung lautet: Zeitstempel, IP-Adresse,
    Pid, Z&auml;hler. Diese Reihenfolge hat einen Sinn, aber es sollte an 
dieser Stelle
    ausdr&uuml;cklich betont werden, dass Applikationen nicht versuchen 
sollten, diese
    Kodierung wieder zu analysieren..
    Programme sollten die komplette kodierte <code>UNIQUE_ID</code>
    als in sich geschlossene Einheit betrachten, die mit anderen
    <code>UNIQUE_ID</code>-Variablen nur auf Gleichheit verglichen
    werden kann.</p>

    <p>Die Reihenfolge wurde gew&auml;hlt, damit die Kodierung ge&auml;ndert 
werden
    kann, ohne dass Sie sich Sorgen &uuml;ber Kollisionen mit
    <code>UNIQUE_ID</code>-Datenbank machen m&uuml;ssen. Die neue Kodierung
    sollte ebenfalls den Zeitstempel als erstes Element verwenden, darf  jedoch
    ansonsten dasselbe Alphabet und dieselbe Bitl&auml;nge verwenden. Da die
    Zeitstempel im Wesentlichen eine ansteigende Sequenz sind,
    reicht ein Pausen-Flag f&uuml;r die Sekunde aus, zu der alle Rechner des 
Clusters 
    die Verarbeitung von Anfragen unterbrechen, das Kodierungsformat
    wechseln und anschlie&szlig;end die Arbeit mit der neuen Kodierung wieder
    aufnehmen.
    </p>

    <p>Dies halten wir f&uuml;r eine relativ portable L&ouml;sung dieses 
Problems, die
    auch f&uuml;r Multithread-Systeme wie Windows NT &uuml;bernommen und 
zuk&uuml;nftigen
    Bed&uuml;rfnissen angepasst werden kann. Die erzeugten Bezeichnungen sind im
    Prinzip ewig g&uuml;ltig, weil zuk&uuml;nftige Bezeichnungen bei Bedarf mit 
einer
    gr&ouml;&szlig;eren L&auml;nge erzeugt werden k&ouml;nnen. Eine
    Kommunikation zwischen den Rechnern des Clusters ist abgesehen von der
    nicht weiter ins Gewicht fallenden NTP-Synchronisation nicht erforderlich.
    Eine Kommunikation zwischen den HTTPD-Prozessen ist ebenfalls nicht
    notwendig (sie findet implizit &uuml;ber die vom Betriebssystemkernel
    zugewiesene Pid statt). In ganz speziellen Situationen kann die Bezeichnung
    verk&uuml;rzt, werden, wobei dann jedoch zus&auml;tzliche Annahmen 
erforderlich sind
    (die 32 Bit lange IP-Addresse ist beispielsweise &uuml;bertrieben f&uuml;r
    jede einzelne Site, aber es gibt keinen k&uuml;rzeren und dennoch
    portablen Ersatz daf&uuml;r). </p>
</section>


</modulesynopsis>

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to