home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 November / CMCD1104.ISO / Software / Complet / Apache / apache_2.0.52-win32-x86-no_ssl.msi / Data.Cab / F278377_mod_unique_id.xml < prev    next >
Extensible Markup Language  |  2004-04-17  |  10KB  |  200 lines

  1. <?xml version="1.0"?>
  2. <!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">
  3. <?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
  4. <!-- $Revision: 1.3.2.5 $ -->
  5.  
  6. <!--
  7.  Copyright 2002-2004 The Apache Software Foundation
  8.  
  9.  Licensed under the Apache License, Version 2.0 (the "License");
  10.  you may not use this file except in compliance with the License.
  11.  You may obtain a copy of the License at
  12.  
  13.      http://www.apache.org/licenses/LICENSE-2.0
  14.  
  15.  Unless required by applicable law or agreed to in writing, software
  16.  distributed under the License is distributed on an "AS IS" BASIS,
  17.  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18.  See the License for the specific language governing permissions and
  19.  limitations under the License.
  20. -->
  21.  
  22. <modulesynopsis metafile="mod_unique_id.xml.meta">
  23.  
  24. <name>mod_unique_id</name>
  25. <description>Provides an environment variable with a unique
  26. identifier for each request</description>
  27. <status>Extension</status>
  28. <sourcefile>mod_unique_id.c</sourcefile>
  29. <identifier>unique_id_module</identifier>
  30.  
  31. <summary>
  32.  
  33.     <p>This module provides a magic token for each request which is
  34.     guaranteed to be unique across "all" requests under very
  35.     specific conditions. The unique identifier is even unique
  36.     across multiple machines in a properly configured cluster of
  37.     machines. The environment variable <code>UNIQUE_ID</code> is
  38.     set to the identifier for each request. Unique identifiers are
  39.     useful for various reasons which are beyond the scope of this
  40.     document.</p>
  41. </summary>
  42.  
  43. <section id="theory">
  44.     <title>Theory</title>
  45.  
  46.     <p>First a brief recap of how the Apache server works on Unix
  47.     machines. This feature currently isn't supported on Windows NT.
  48.     On Unix machines, Apache creates several children, the children
  49.     process requests one at a time. Each child can serve multiple
  50.     requests in its lifetime. For the purpose of this discussion,
  51.     the children don't share any data with each other. We'll refer
  52.     to the children as httpd processes.</p>
  53.  
  54.     <p>Your website has one or more machines under your
  55.     administrative control, together we'll call them a cluster of
  56.     machines. Each machine can possibly run multiple instances of
  57.     Apache. All of these collectively are considered "the
  58.     universe", and with certain assumptions we'll show that in this
  59.     universe we can generate unique identifiers for each request,
  60.     without extensive communication between machines in the
  61.     cluster.</p>
  62.  
  63.     <p>The machines in your cluster should satisfy these
  64.     requirements. (Even if you have only one machine you should
  65.     synchronize its clock with NTP.)</p>
  66.  
  67.     <ul>
  68.       <li>The machines' times are synchronized via NTP or other
  69.       network time protocol.</li>
  70.  
  71.       <li>The machines' hostnames all differ, such that the module
  72.       can do a hostname lookup on the hostname and receive a
  73.       different IP address for each machine in the cluster.</li>
  74.     </ul>
  75.  
  76.     <p>As far as operating system assumptions go, we assume that
  77.     pids (process ids) fit in 32-bits. If the operating system uses
  78.     more than 32-bits for a pid, the fix is trivial but must be
  79.     performed in the code.</p>
  80.  
  81.     <p>Given those assumptions, at a single point in time we can
  82.     identify any httpd process on any machine in the cluster from
  83.     all other httpd processes. The machine's IP address and the pid
  84.     of the httpd process are sufficient to do this. So in order to
  85.     generate unique identifiers for requests we need only
  86.     distinguish between different points in time.</p>
  87.  
  88.     <p>To distinguish time we will use a Unix timestamp (seconds
  89.     since January 1, 1970 UTC), and a 16-bit counter. The timestamp
  90.     has only one second granularity, so the counter is used to
  91.     represent up to 65536 values during a single second. The
  92.     quadruple <em>( ip_addr, pid, time_stamp, counter )</em> is
  93.     sufficient to enumerate 65536 requests per second per httpd
  94.     process. There are issues however with pid reuse over time, and
  95.     the counter is used to alleviate this issue.</p>
  96.  
  97.     <p>When an httpd child is created, the counter is initialized
  98.     with ( current microseconds divided by 10 ) modulo 65536 (this
  99.     formula was chosen to eliminate some variance problems with the
  100.     low order bits of the microsecond timers on some systems). When
  101.     a unique identifier is generated, the time stamp used is the
  102.     time the request arrived at the web server. The counter is
  103.     incremented every time an identifier is generated (and allowed
  104.     to roll over).</p>
  105.  
  106.     <p>The kernel generates a pid for each process as it forks the
  107.     process, and pids are allowed to roll over (they're 16-bits on
  108.     many Unixes, but newer systems have expanded to 32-bits). So
  109.     over time the same pid will be reused. However unless it is
  110.     reused within the same second, it does not destroy the
  111.     uniqueness of our quadruple. That is, we assume the system does
  112.     not spawn 65536 processes in a one second interval (it may even
  113.     be 32768 processes on some Unixes, but even this isn't likely
  114.     to happen).</p>
  115.  
  116.     <p>Suppose that time repeats itself for some reason. That is,
  117.     suppose that the system's clock is screwed up and it revisits a
  118.     past time (or it is too far forward, is reset correctly, and
  119.     then revisits the future time). In this case we can easily show
  120.     that we can get pid and time stamp reuse. The choice of
  121.     initializer for the counter is intended to help defeat this.
  122.     Note that we really want a random number to initialize the
  123.     counter, but there aren't any readily available numbers on most
  124.     systems (<em>i.e.</em>, you can't use rand() because you need
  125.     to seed the generator, and can't seed it with the time because
  126.     time, at least at one second resolution, has repeated itself).
  127.     This is not a perfect defense.</p>
  128.  
  129.     <p>How good a defense is it? Suppose that one of your machines
  130.     serves at most 500 requests per second (which is a very
  131.     reasonable upper bound at this writing, because systems
  132.     generally do more than just shovel out static files). To do
  133.     that it will require a number of children which depends on how
  134.     many concurrent clients you have. But we'll be pessimistic and
  135.     suppose that a single child is able to serve 500 requests per
  136.     second. There are 1000 possible starting counter values such
  137.     that two sequences of 500 requests overlap. So there is a 1.5%
  138.     chance that if time (at one second resolution) repeats itself
  139.     this child will repeat a counter value, and uniqueness will be
  140.     broken. This was a very pessimistic example, and with real
  141.     world values it's even less likely to occur. If your system is
  142.     such that it's still likely to occur, then perhaps you should
  143.     make the counter 32 bits (by editing the code).</p>
  144.  
  145.     <p>You may be concerned about the clock being "set back" during
  146.     summer daylight savings. However this isn't an issue because
  147.     the times used here are UTC, which "always" go forward. Note
  148.     that x86 based Unixes may need proper configuration for this to
  149.     be true -- they should be configured to assume that the
  150.     motherboard clock is on UTC and compensate appropriately. But
  151.     even still, if you're running NTP then your UTC time will be
  152.     correct very shortly after reboot.</p>
  153.  
  154.     <p>The <code>UNIQUE_ID</code> environment variable is
  155.     constructed by encoding the 112-bit (32-bit IP address, 32 bit
  156.     pid, 32 bit time stamp, 16 bit counter) quadruple using the
  157.     alphabet <code>[A-Za-z0-9@-]</code> in a manner similar to MIME
  158.     base64 encoding, producing 19 characters. The MIME base64
  159.     alphabet is actually <code>[A-Za-z0-9+/]</code> however
  160.     <code>+</code> and <code>/</code> need to be specially encoded
  161.     in URLs, which makes them less desirable. All values are
  162.     encoded in network byte ordering so that the encoding is
  163.     comparable across architectures of different byte ordering. The
  164.     actual ordering of the encoding is: time stamp, IP address,
  165.     pid, counter. This ordering has a purpose, but it should be
  166.     emphasized that applications should not dissect the encoding.
  167.     Applications should treat the entire encoded
  168.     <code>UNIQUE_ID</code> as an opaque token, which can be
  169.     compared against other <code>UNIQUE_ID</code>s for equality
  170.     only.</p>
  171.  
  172.     <p>The ordering was chosen such that it's possible to change
  173.     the encoding in the future without worrying about collision
  174.     with an existing database of <code>UNIQUE_ID</code>s. The new
  175.     encodings should also keep the time stamp as the first element,
  176.     and can otherwise use the same alphabet and bit length. Since
  177.     the time stamps are essentially an increasing sequence, it's
  178.     sufficient to have a <em>flag second</em> in which all machines
  179.     in the cluster stop serving and request, and stop using the old
  180.     encoding format. Afterwards they can resume requests and begin
  181.     issuing the new encodings.</p>
  182.  
  183.     <p>This we believe is a relatively portable solution to this
  184.     problem. It can be extended to multithreaded systems like
  185.     Windows NT, and can grow with future needs. The identifiers
  186.     generated have essentially an infinite life-time because future
  187.     identifiers can be made longer as required. Essentially no
  188.     communication is required between machines in the cluster (only
  189.     NTP synchronization is required, which is low overhead), and no
  190.     communication between httpd processes is required (the
  191.     communication is implicit in the pid value assigned by the
  192.     kernel). In very specific situations the identifier can be
  193.     shortened, but more information needs to be assumed (for
  194.     example the 32-bit IP address is overkill for any site, but
  195.     there is no portable shorter replacement for it). </p>
  196. </section>
  197.  
  198.  
  199. </modulesynopsis>
  200.