mirror of
https://github.com/apache/httpd.git
synced 2025-05-30 01:07:09 +03:00
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@421136 13f79535-47bb-0310-9956-ffa450edef68
175 lines
7.9 KiB
XML
175 lines
7.9 KiB
XML
<?xml version="1.0" encoding="EUC-KR" ?>
|
|
<!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">
|
|
<?xml-stylesheet type="text/xsl" href="../style/manual.ko.xsl"?>
|
|
<!-- English Revision: 105989:420990 (outdated) -->
|
|
|
|
<!--
|
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
contributor license agreements. See the NOTICE file distributed with
|
|
this work for additional information regarding copyright ownership.
|
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
(the "License"); you may not use this file except in compliance with
|
|
the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
-->
|
|
|
|
<modulesynopsis metafile="mod_unique_id.xml.meta">
|
|
|
|
<name>mod_unique_id</name>
|
|
<description>각 요청마다 유일한 식별자를 가지는 환경변수를
|
|
제공한다</description>
|
|
<status>Extension</status>
|
|
<sourcefile>mod_unique_id.c</sourcefile>
|
|
<identifier>unique_id_module</identifier>
|
|
|
|
<summary>
|
|
|
|
<p>이 모듈은 어떤 특별한 상황에서도 "모든" 요청중에서
|
|
유일하도록 보장된 식별자(identifier)를 모든 요청에 제공한다.
|
|
심지어 이 식별자는 특별하게 구성한 클러스터의 여러 컴퓨터들
|
|
중에서도 유일하다. 각 요청마다 환경변수
|
|
<code>UNIQUE_ID</code>를 설정한다. 유일한 식별자는 여러가지
|
|
용도로 사용할 수 있지만, 설명은 이 문서의 범위를 넘어선다.</p>
|
|
</summary>
|
|
|
|
<section id="theory">
|
|
<title>이론</title>
|
|
|
|
<p>먼저 유닉스 시스템에서 아파치 서버가 어떻게 동작하는지
|
|
간략히 살펴보자. Windows NT는 현재 이 기능을 지원하지 않는다.
|
|
유닉스에서 아파치는 여러 자식을 만들고, 자식 프로세스는
|
|
한번에 한 요청씩 처리한다. 자식은 실행중에 여러 요청을
|
|
처리한다. 여기서 중요한 것은 자식들이 서로 자료를
|
|
공유하지 않는다는 점이다. 앞으로 자식을 httpd 프로세스라고
|
|
한다.</p>
|
|
|
|
<p>여러 컴퓨터로 웹사이트를 서비스한다면 클러스터(cluster)라고
|
|
부른다. 각 컴퓨터는 여러 아파치를 실행할 수 있다. 이들 모두를
|
|
"우주"로 보면, 클러스터에 있는 컴퓨터들간에 많은 통신없이
|
|
각 요청마다 우주에서 유일한 식별자를 만들 수 있다.</p>
|
|
|
|
<p>클러스터에 있는 컴퓨터는 다음 요구사항을 만족해야 한다.
|
|
(컴퓨터를 한대만 사용하더라도 컴퓨터 시간을 NTP와 동기해야
|
|
한다.)</p>
|
|
|
|
<ul>
|
|
<li>컴퓨터 시간은 NTP나 다른 네트웍 시간 프로토콜과
|
|
동기화된다.</li>
|
|
|
|
<li>컴퓨터의 호스트명이 모두 다르다. 그래서 모듈이
|
|
호스트명으로 찾으면 클러스터에 있는 각 컴퓨터마다 다른
|
|
IP 주소를 얻는다.</li>
|
|
</ul>
|
|
|
|
<p>운영체제에서 pid (프로세스 id)가 32비트에 들어간다고
|
|
가정한다. 운영체제가 pid로 32비트 이상을 사용한다면 간단하지만
|
|
코드를 수정해야 한다.</p>
|
|
|
|
<p>이런 가정하에 우리는 어떤 시점에서 클러스터의 어떤 컴퓨터에
|
|
있는 어떤 httpd 프로세스를 다른 모든 httpd 프로세스들과
|
|
구별할 수 있다. 컴퓨터의 IP 주소와 httpd 프로세스의 pid만으로도
|
|
충분히 구별할 수 있다. 그래서 요청에 대해 유일한 구별자를
|
|
만드려면 시간차를 구별할 수만 있으면 된다.</p>
|
|
|
|
<p>시간을 구별하기위해 유닉스 시간(timestamp, 세계 표준시로
|
|
1970년 1월 1일 이후 지난 초)과 16비트 카운터를 사용한다.
|
|
유닉스 시간은 초단위이고, 카운터는 일 초동안 65536까지
|
|
증가한다. <em>( ip_addr, pid, time_stamp, counter )</em>
|
|
묶음은 어떤 httpd 프로세스에서 일 초동안 65536 요청을 구별할
|
|
수 있다. 그러나 카운터는 pid를 재사용하는 문제를 해결해야
|
|
한다.</p>
|
|
|
|
<p>httpd 자식을 만들면 카운터는 ( 현재 밀리초 나누기 10 )을
|
|
65536으로 나눈 나머지가 된다. (몇몇 시스템의 밀리초 시간에서
|
|
하위 비트가 일치하지않는 문제때문에 이 공식을 만들었다.)
|
|
유일한 식별자를 만들때 사용하는 시간은 웹서버가 요청을 받은
|
|
시간이다. 카운터는 식별자를 만들때마다 증가한다 (그리고
|
|
다시 시작한다).</p>
|
|
|
|
<p>커널은 프로세스를 포크할때(fork) 각 프로세스에 pid를
|
|
할당하고, pid는 다시 시작할 수 있다. (pid는 많은 유닉스에서
|
|
16비트이지만, 최근 시스템은 32비트로 확장했다.) 그래서 시간이
|
|
지나면 같은 pid를 재사용할 수 있다. 그러나 같은 시간에 pid를
|
|
재사용하지 않는다면 위의 묶음은 유일하다. 즉, 우리는 시스템이
|
|
일초동안 프로세스를 65536개 이상 만들지 않는다고 가정한다.
|
|
(어떤 유닉스에서는 32768개 이상 프로세스를 만들면 pid 재사용
|
|
문제가 발생할 수 있지만, 이것조차도 일어날 것같지 않다.)</p>
|
|
|
|
<p>시간이 어떤 이유에서건 반복된다고 가정해보자. 즉, 시스템
|
|
시계가 꼬여서 시간이 과거로 돌아가는 (혹은 시계가 너무 앞서가서
|
|
올바로 재설정한후 미래에 같은 시간이 되는) 경우다. 이 경우
|
|
pid와 시간을 모두 재사용할 수 있다. 카운터의 초기화 공식은
|
|
이 문제를 해결하려고 고안되었다. 우리는 실제 무작위 숫자로
|
|
카운터를 초기화하길 원하지만, 많은 시스템에서 이런 수를
|
|
쉽게 얻을 수 없다. (<em>예를 들어</em>, seed가 필요하기때문에
|
|
rand()를 사용할 수 없고, 시간은 최소한 일초 단위이기때문에
|
|
시간으로 seed로 사용할 수 없다.) 즉 완벽한 해결책이 없다.</p>
|
|
|
|
<p>그럼 이 방법은 얼마나 괜찮을까? 컴퓨터중 하나가 요청을
|
|
초당 최대 500개 (시스템은 일반적으로 정적인 파일을 전송하는
|
|
것 이상의 작업을 하므로 이 글을 쓰는 시점에서 상당히 높은
|
|
값이다.) 서비스한다고 가정하자. 동시에 얼마만큼의 클라이언트를
|
|
처리하는가에 따라 자식의 개수가 결정된다. 그러나 우리는
|
|
비관적으로 한 자식이 요청을 초당 500개 처리할 수 있다고
|
|
가정한다. 재사용한 pid를 가진 자식의 500개 요청과 이전 자식의
|
|
500개 요청의 카운터값이 겹칠 수 있는 카운터 시작값 경우수는
|
|
1000개이다. 그래서 (초단위에서) 자식이 카운터값을 반복하여
|
|
유일성이 깨질 확률은 1.5%이다. 이것은 매우 비관적인 가정이며,
|
|
실제 이럴 경우는 상당히 더 낮다. 그래도 시스템에서 이런
|
|
일이 발생할 것 같다면 (소스를 수정하여) 카운터를 32비트로
|
|
만들어라.</p>
|
|
|
|
<p>섬머타임때문에 시계가 "뒤로 가는" 것을 걱정할지도 모른다.
|
|
그러나 여기서 사용하는 시간은 국제 표준시(UTC), 즉 시간이
|
|
"항상" 앞으로 가므로 문제가 없다. x86기반 유닉스에서는
|
|
적절한 설정이 필요하다. 메인보드 시계가 UTC를 사용하도록
|
|
설정해야 한다. 그러나 NTP를 사용한다면 재시작후 조금 지나면
|
|
UTC 시간에 올바로 맞춘다.</p>
|
|
|
|
<p>환경변수 <code>UNIQUE_ID</code>는 MIME base64 인코딩과
|
|
비슷한 방법으로 112비트 (32비트 IP 주소, 32비트 pid, 32비트
|
|
시간, 16비트 카운터) 묶음을 알파벳 <code>[A-Za-z0-9@-]</code>로
|
|
표현한다. 실제 MIME base64 알파벳은
|
|
<code>[A-Za-z0-9+/]</code>이지만 <code>+</code>와
|
|
<code>/</code>는 URL에서 특별한 의미로 사용하므로 제외했다.
|
|
모든 값을 네트웍 바이트순서로 인코딩하기때문에 다른 바이트순서를
|
|
사용하는 아키텍쳐간에 값이 같다. 실제 인코딩 순서는
|
|
시간, IP 주소, pid, 카운터 순서이다. 이 순서에는 어떤 목적이
|
|
있지만, 프로그램은 인코딩 순서에 의존하여 값들을 분석하면
|
|
안됨을 강조한다. 프로그램은 인코딩된 <code>UNIQUE_ID</code>
|
|
전체를 한 단위로 생각하고, 다른 <code>UNIQUE_ID</code>와
|
|
동일한지만 비교할 수 있다.</p>
|
|
|
|
<p>순서는 앞으로 기존의 <code>UNIQUE_ID</code> 데이터베이스와
|
|
충돌을 염려하지않고 인코딩을 변경할 수 있도록 고안했다.
|
|
새로운 인코딩은 첫 항목으로 시간을 사용하거나, 같은 알파벳과
|
|
비트 길이를 사용할 수도 있다. 시간이 기본적으로 증가하는 값이므로
|
|
클러스터에 있는 모든 컴퓨터가 요청 서비스를 중단하고 이전
|
|
인코딩 형식을 그만 사용하기위해 <em>기준 초(flag second)</em>만으로
|
|
충분하다. 이후 요청을 재게하고 새로운 인코딩을 시작할 수
|
|
있다.</p>
|
|
|
|
<p>우리는 이 방법이 이 문제에 대하여 상대적으로 포팅가능한
|
|
해결책이라고 믿는다. 이 방법은 Windows NT와 같은 멀티쓰레드
|
|
시스템으로 확장할 수 있고, 앞으로 용도에 따라 확장할 수
|
|
있다. 미래에 필요한만큼 더 긴 식별자를 만들 수 있기때문에
|
|
생성한 식별자는 기본적으로 영원한 수명을 가진다. 기본적으로
|
|
클러스터의 컴퓨터들 사이에 통신이 필요없고 (부하가 작은
|
|
NTP 동기만 필요하다), httpd 프로세스 사이에 통신도 필요없다
|
|
(커널이 부여하는 pid값이 암묵적인 통신이다). 매우 특이한
|
|
상황이라면 인식자 크기를 줄일 수 있지만 더 많은 정보를
|
|
가정해야 한다. (예를 들어, 어떤 사이트에서 32비트 IP 주소
|
|
구분은 불필요하게 크지만, 이를 줄이는 방법은 상황에 따라
|
|
다르다.) </p>
|
|
</section>
|
|
|
|
|
|
</modulesynopsis>
|