목차
1. 다채로운 웹서버
2. 간단한 펄 웹 서버
3.진짜 웹서버가 하는 일
-단계1: 클라이언트 커넥션 수락
-단계2: 요청 메세지 수신
-단계3: 요청 처리
-단계4: 리소스의 매핑과 접근
-단계5: 응답 만들기
-단계6: 응답 보내기
-단계7: 로깅
네트워크에 연결된 표준 컴퓨터 시스템에서 동작(Apache, Nginx 등등).
프린터, 가전제품 등에 내장되는 서버. 보통 최소한의 기능만 제공
(Apache 웹 서버 코어는 코드 50,000줄 이상)
풍부한 리소스 자원
가상 호스팅
접근 제어
로깅
설정
모니터링
이 외 각종 기능들이 필요하다.
However, 최소한으로 기능하는 HTTP서버라면 30줄 이하의 Perl코드로 만들 수 있다.
<코드에 대한 주석>
1)8080포트 기본 설정
2)로컬 TCP소켓을 생성, 커넥션을 기다리도록 설정
3)시작 메세지 출력
4)커넥션
6)요청 메세지 출력
7)응답 메시지 생성
기존 맺고 있는 커넥션 있다면 그것 사용, 없다면 새로운 커넥션 열기.
클라이언트에서 TCP커넥션 요청이 오면, 커넥션 맺은 후 IP주소 추출하여 클라이언트 확인한다.
웹 서버는 어떤 커넥션이든 마음대로 거절하거나 닫을 수 있다.
client의 ip주소, 호스트 명이 인가되지 않았거나 악의적이라 판단할 경우 커넥션 닫는다.
-역방향 DNS, ident 등을 통해 클라이언트를 알아낼 수도 있다.
-커넥션에 데이터가 도착하면, 웹 서버는 그 데이터를 읽고 파싱하여 request메세지 구성한다.
-요청 메시지 파싱할 때 웹 서버가 하는 일
1)요청줄 파싱해서 메서드, URI, 버전번호 찾는다. 각 값은 스페이스 한 개로 분리. 요청줄은 캐리지 리턴 (CRLF)줄바꿈 문자열로 끝난다.
2)메시지 헤더 읽는다. (각 메시지 헤더는 CRLF로 끝남)
3)헤더 끝을 의미하는 CRLF로 끝나는 빈 줄 찾는다.(있다면)
4)body 읽는다(있다면)
-한 번에 하나씩 요청 처리.
-구현은 간단하지만 처리 도중 모든 커넥션이 무시되므로 심각한 성능 문제 발생.
-로드가 적은 서버, 진단도구로만 적당.
-여러 요청을 동시에 처리하기 위해 여러 프로세스, 스레드 할당.
대부-분의 멀티스레드 웹 서비스가 스레드/프로세스의 최대 개수 제한을 건다.
(매 커넥션마다 스레드/프로세스를 하나씩 할당하면 수백, 수천, 수만 개의 동시 커넥션을 처리할 때 too much 메모리/시스템 리소스 소비하게 되므로)
-대량 커넥션 지원 위해 많은 웹서버가 다중 I/O 채택.
-커넥션에 할 일이 있을 때 해당 커넥션에 대해 작은 양의 처리가 수행됨.
-그 처리 완료 후 커넥션은 다음 작업을 위해 열린 커넥션 목록으로 되돌아감.
-어떤 커넥션에 대해 작업을 수행하는 것은 그 커넥션에 실제 해야할 일이 있을 때 뿐.
-스레드/프로세스는 유휴 상태의 커넥션에 매여 기다리느라 리소스 낭비하지 않아도 된다.
-멀티스레딩 + 다중화 결합된 아키텍쳐.
-여러 개의 스레드(보통 하나의 물리적 프로세스)는 각각 열려있는 커넥션을 감시하고 각 커넥션에 대해 조금씩 작업을 수행한다.
POST를 비롯한 몇몇 메서드는 요청 메시지에 엔터티 본문이 있을 것을 요구한다. 그 외 OPTIONS를 비롯한 다수의 메서드는 요청에 본문이 있는 것을 허용하되 요구하지 않는다. 많지는 않지만 GET과 같이 요청 메시지에 엔터티 본문이 있는 것을 금지하는 메서드도 있다.
웹 서버가 지원하는 여러 종류의 리소스 매핑 중 가ㅈ아 단순한 형태는 요청 URI를 웹 서버의 파일 시스템 안에 있는 파일 이름으로 사용하는 것이다. 일반적으로 웹 서버 파일 시스템의 특정 폴더를 웹 콘텐츠를 위해 예약해둔다. 이 폴더를 docroot라 한다.
웹 서버는 request message URI를 가져와 docroot뒤에 붙인다.
예)
DocumentRoot /usr/local/httpd/files
request: GET /specials/saw-blades.gif HTTP/1.0
리소스 위치: /usr/local/httpd/files/specials/saw-blades.gif
제대로된 웹서버는 request의 상대경로 url이 docroot를 벗어났다면 이를 허용하지 않는다.
../
같은 건 사용 불가능하다는 얘기.
docroot를 다르게 지정해서 한 서버가 복수의 사이트를 hosting할 수 있다.
a사이트의 docroot는 a/b/c/로 하고,
b사이트의 docroot는 d/e/f로 하면 하나의 서버로 두 사이트 호스팅 가능.
하나의 웹서버가 사용자에 따라 다른 docroots를 제공해서, 각자 개인의 웹사이트를 만들 수 있다.
보통 빗금(/)과 물결표(~)다음에 사용자 이름 오는 것으로 시작하는 URI는 그 사용자의 개인 문서 루트를 가리킨다.
예:
GET /~junsu/index.html HTTP/1.0
->www.junsu.com
GET /~ohsung/index.html HTTP/1.0
-> www.marrys-antiques.com
특정 파일이 아니라 특정 디렉터리를 가리키는 URL 요청이 왔을 때 아래 같은 행동 취하도록 설정 가능!
1) 에러 반환
2) index파일 반환(해당 디렉토리에 관한)
3) 디렉터리 탐색 후 그 내용 담은 html페이지 반환(디렉터리 파일들의 크기, 변경일, 링크 열거한 HTML파일 반환, 하지만 일반적으로 발견할 수 없는 파일도 드러나게 된다는 단점이 있다)
pass
pass(이해가 잘 안된다ㅜ)
ip주소에 근거하여 접근 제어 가능.
특정 리소스에 접근 하기 위해 비밀번호 묻기 가능.
서버는 response body의 MIME타입 결정해야 한다. MIME타입과 리소스를 연결하는 방법엔 몇가지가 있다.
1) mime.types
파일 확장자 이름 사용
가장 흔한 방법
2)매직 타이핑(Magic typing)
아파치 웹서버는 파일 내용 검사해서 패턴 테이블에 해당하는 패턴이 있는지 찾는다.
느리긴 한데 표준 확장자 없이 이름 지어진 파일을 다룰 때 편리하다.
3)유형 명시(Explicit typing)
파일 확장자, 내용 상관 없이 특정 MIME타입 강제로 때려버림
4)유형 협상(Type negotiation)
한 리소스가 여러 종류의 형식에 속하도록 설정 할 수 있다.
이때 웹 서버가 사용자와의 협상 과정을 통해 사용하기 가장 좋은 형식을 판별할 것인지의 여부도 설정할 수 있다.(말이 좀 이상하다)
-리소스 영구적/일시적으로 옮겨졌을 때 redirect
-과부하 받을 때 부하 덜걸린 서버로 redirect
-client가 URI요청 시 빗금(/) 빠뜨렸을 떄 빗금 추가한 URI로 리다이렉트
비지속적 커넥션일 경우, 서버는 모드 메세지를 전송했을 때 커넥션 종료시킴
지속적 커넥션일 경우 유지(필요한 경우)
트랙젝션 완료 시 로그남김.