Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2부 5장] 웹 서버 #6

Open
qkrqudcks7 opened this issue Aug 20, 2022 · 8 comments
Open

[2부 5장] 웹 서버 #6

qkrqudcks7 opened this issue Aug 20, 2022 · 8 comments

Comments

@qkrqudcks7
Copy link

qkrqudcks7 commented Aug 20, 2022

5. 웹 서버

  • 여러 종류의 소프트웨어 및 하드웨어 웹 서버 알아보기
  • 어떻게 웹 서버가 HTTP 트랜잭션을 처리하는지 알아보기

5.1 다채로운 웹 서버

5.1.1 웹 서버 기능

  • 웹 서버는 자신이 제공하는 리소스를 관리하고 웹 서버를 설정, 통제, 확장하기 위한 관리 기능을 제공한다.
  • 웹 서버는 HTTP 프로토콜을 구현하고, 웹 리소스를 관리하고, 웹 서버 관리 기능을 제공한다.
  • 웹 서버는 TCP 커넥션 관리의 책임을 운영체제와 나눠 갖는다.

5.1.2 다목적 소프트웨어 웹 서버

  • 네트워크에 연결된 표준 컴퓨터 시스템에서 동작한다.
  • apache 같은 오픈 소스 또는 microsoft 같은 상용 소프트웨어들이 있다.

웹서버 시장 점유율 (넷크래프트 2021년 기준)

image

5.2 웹 서버가 하는 일

image

  1. 커넥션 맺기 : 원치 않는 클라이언트라면 닫는다
  2. HTTP 요청 받기
  3. 요청 처리하기
  4. 리소스에 접근하기
  5. HTTP 응답 만들기
  6. 응답을 클라이언트에게 보내기
  7. 트랜잭션을 로그로 남기기 : 로그파일에 트랜잭션 완료에 대한 기록을 남긴다

5.3 웹 서버가 HTTP 트랜잭션을 처리하는 방법

1. 클라이언트 커넥션 수락

  • 클라이언트가 서버와 지속 커넥션을 맺고 있다면, 그 커넥션 사용한다.
  • 커넥션이 없다면, 클라이언트와 서버간 새 커넥션을 연다

새 커넥션 다루기

  • 클라이언트가 서버에 TCP 커넥션을 요청하면, 서버는 그 커넥션을 맺고 TCP 커넥션에서 IP 주소를 추출하여 커넥션 맞은편에 어떤 클라이언트가 있는지 확인한다.
  • 새 커넥션이 맺어지고 받아들여지면, 서버는 새 커넥션을 커넥션 목록에 추가하고 오가는 데이터를 지켜보기 위한 준비를 한다.
  • 웹 서버는 어떤 커넥션이든 마음대로 거절하거나 즉시 닫을 수 있다.

클라이언트 호스트 명 식별

image

  • 역방향 DNS(Reverse DNS) 를 사용해서 클라이언트의 IP 주소를 클라이언트의 호스트 명으로 변환하도록 설정한다.
  • 웹 서버는 클라이언트의 호스트명을 구체적인 접근 제어와 로깅을 위해 사용할 수 있다.
  • 호스트 명 룩업(hostname lookup)은 웹 트랜잭션을 느려지게 할 수 있으므로 대용량 웹 서버들은 꺼둔다.

2. 요청 메세지 수신

  • 커넥션에 데이터가 도착하면, 웹 서버는 네트워크 커넥션에서 그 데이터를 읽어 들이고 파싱하여 요청 메세지를 구성한다.

image

  • 요청줄을 파싱하여 요청 메서드, URI, HTTP version을 찾는다.
  • 메시지 헤더를 읽는다. 각 메세지 헤더는 CRLF로 끝난다.
  • 헤더의 끝을 의미하는 CRLF로 끝나는 빈 줄을 찾아낸다.(존재하면)
  • 요청 본문이 있다면, 읽어 들인다.

웹 서버는 입력 데이터를 네트워크로부터 불규칙적으로 받는다. 커넥션이 언제 끊킬지 모르니,
파싱해서 데이터를 이해할 수 있는 수준의 분량을 확보할 때까지 메시지 일부분을 메모리에 임시로 저장한다.

커넥션 입력/출력 처리 아키텍처

image

단일 스레드 문제점

  • 치명적인 성능 문제(느리다)

멀티 프로세스와 멀티 스레드 웹 서버 문제점

  • 클라이언트와 커넥션이 생길 때마다 프로세스/스레드를 할당하는 것은 많은 리소스가 할당된다.
  • idle 상태의 커넥션에 대해서도 스레드와 프로세스는 여전히 할당되어 낭비로 이어진다.

다중 I/O 서버

  • 대량의 커넥션을 지원하기 위해, 많은 웹 서버는 다중 아키텍처를 채택했다.
  • 모든 커넥션은 동시에 그 활동을 감시당한다.
  • 커넥션 상태가 바뀌면, 그 커넥션에 대한 작은 양의 처리가 수행된다.
  • 처리가 완료되면, 커넥션은 다음번 상태 변경을 위해 열린 커넥션 목록으로 돌아간다.
  • 커넥션에 대한 작업을 수행하는 것은 그 커넥션에 해야 할 일이 있을 때 뿐이다.
  • 스레드와 프로세스는 idle상태의 커넥션에 매여 기다리느라 리소스를 낭비하지 않는다.

3. 요청 처리

  • 서버가 요청을 받으면, 서버는 요청으로부터 메서드, 리소스, 헤더, 본문(없는 경우도 있다)을 얻어내어 처리한다.

4. 리소스의 매핑과 접근

  • 웹 서버는 리소스 서버다. html과 jpeg 같은 정적 콘텐츠를 제공한다.
  • 서버 위에서 동작하는 리소스 생성 애플리케이션을 통해 만들어진 동적 콘텐츠도 제공한다.
  • 웹 서버가 클라이언트에 콘텐츠를 전달하려면, 요청 메시지에 URI에 대응하는 콘텐츠나 생성기를 웹 서버에서 찾아서 콘텐츠 원천을 식별해야 한다.

Docroot : 정적 컨텐츠 리소스 매핑

image

  • 리소스 매핑의 가장 단수한 형태는 요청 URI를 웹 서버의 파일 시스템 안에 있는 파일 이름으로 사용하는 것이다.
    일반적으로 웹 서버 파일 시스템의 특별한 폴더를 웹 콘텐츠를 위해 예약해둔다.
    이 폴더는 문서 루트 혹은 Docroot라고 부른다.

가상 호스팅 된 docroot

  • 가상 호스팅 웹서버는 각 사이트에 그들만의 분리된 문서 루트를 주는 방법으로, 한 웹서버에서 여러 개의 웹사이트를 호스팅한다.
  • 가상 호스팅 웹서버는 URI나 Host 헤더에서 얻은 IP 주소나 호스트 명을 이용해 올바른 문서 루트를 식별한다.

사용자 홈 디렉터리 docroots

  • 사용자들이 한대의 웹서버에서 각자의 개인 웹사이트를 만들 수 있도록 해주는 것이다.
  • 보통 /과 물결표~ 다음에 사용자 이름이 오는 것으로 시작하는 URI는 그 사용자의 개인 문서 루트를 가리킨다.
  • 개인 docroot는 주로 사용자 홈 디렉터리 안에 있는 public_html로 불리는 디렉터리지만, 설정에 따라 다르다.

디렉터리 목록

  • 대부분의 웹 서버는 클라이어트가 디렉터리 URL을 요청했을 때 다음과 같이 몇 가지 다른 행동을 취하도록 설정할 수 있다.
    • 에러를 반환한다.
    • 디렉터리 대신 특별한 '색인 파일'을 반환한다.
    • 디렉터리를 탐색해서 그 내용을 담은 HTML 페이지를 반환한다.

동적 콘텐츠 리소스 매핑

image

  • 웹 서버는 URI를 동적 리소스에 매핑할 수 있다. 즉, 요청에 맞게 콘텐츠를 생성하는 프로그램에 URI를 매핑하는 것이다.
  • 웹 서버들 중에서 애플리케이션 서버라 불리는 것들은 웹 서버를 복잡한 백엔드 애플리케이션과 연결하는 일을 한다.

서버사이드 인클루드(Server-Side Includes, SSI)

  • 동적 컨텐츠를 만드는 쉬운 방법( 예) HTML 안에 동적인 내용 추가하는 것)
  • 어떤 리소스가 서버사이드 인클루드를 포함하도록 설정되어 있다면 서버는 그 리소스의 콘텐츠를 클라이언트에 보내기전에 처리한다.
  • 서버는 콘텐츠에 변수 이름이나 내장된 스크립트가 될 수 있는 어떤 특별한 패턴이 있는지 검사하고 특별한 패턴은 변수 값이나 실행가능한 스크립트의 출력값으로 치환된다.

접근 제어

  • 웹 서버는 각각의 리소스에 접근 제어를 할당할 수 있다.
  • 접근 제어된 리소스에 요청이 왔을때 웹 서버는 클라이언트의 IP주소를 근거하여 접근을 제어하거나 비밀번호를 물어볼 수 있다.

5. 응답 만들기

  • 한번 서버가 리소스를 식별하면, 서버는 요청 메서드로 서술되는 동작을 수행한 뒤 응답 메시지를 반환한다.

응답 엔터티

  • MIME 타입을 서술하는 Content-Type 헤더
  • 길이를 서술하는 Content-Length 헤더
  • 실제 응답 본문의 내용

MIME 타입 결정하기

  • 웹 서버에게는 응답 본문의 MIME 타입을 결정해야하는 책임이 있다.

image

mime.types

  • 웹 서버는 MIME 타입을 나타내기 위해 파일 이름의 확장자를 사용할 수 있다.
  • 웹 서버는 각 리소스의 MIME 타입을 계산하기 위해 확장자별 MIME 타입이 담겨 있는 파일을 탐색한다.
  • 이런 확장자 기반 타입 연계가 가장 흔한 방법이다.

리다이렉션

  • 웹 서버는 요청을 수행하기 위해 브라우저가 다른 곳으로 가도록 리다이렉트 할 수 있다.
  • 리다이렉션 응답은 3xx 상태코드로 지칭된다.
  • Location 응답 헤더는 콘텐츠의 새로운 혹은 선호하는 위치에 대한 URI를 포함한다.

리소스가 영구적으로 옮겨진 경우

  • 301 Moved Permanently 상태 코드를 사용한다.

임시로 리소스가 옮겨진 경우

  • 303 See Other, 307 Temporary Redirect 상태 코드를 사용한다.

URL 증강

  • 문맥 정보를 포함하기 위해 재 작성된 URL로 리다이렉트를 한다.
  • 요청이 도착하면 서버는 상태 정보를 내포한 새 URL을 생성하고 사용자를 이 새 URL로 리다이렉트한다.
  • 클라이언트는 상태 정보가 포함된 완전한 URL을 포함한 요청을 다시 한다.
  • 303 See Other와 307 Temporary Redirect 상태 코드를 사용한다.

부하 균형(Load Balancing)

  • 과부화된 서버가 요청을 받으면, 덜 부하가 걸린 서버로 리다이렉트 할 수 있다.
  • 303 See Other와 307 Temporary Redirect 상태 코드를 사용한다.

친밀한 다른 서버가 있을 때

  • 웹 서버가 클라이언트에 대한 정보를 갖고 있을 수 있다.
  • 요청한 클라이언트에 대한 정보를 갖고 있는 다른 서버로 리다이렉트 할 수 있다.
  • 303 See Other와 307 Temporary Redirect 상태 코드를 사용한다.

디렉토리 이름 정규화

  • 클라이언트가 디렉토리 이름에 대한 URI를 요청하는데, 슬래쉬를 빠뜨렸다면 슬래쉬를 추가한 URI로 리다이렉트 한다.

6. 응답 보내기

  • 웹 서버는 요청들 받을 때와 마찬가지로 커넥션 너머로 데이터를 보낼 때도 비슷한 이슈에 직면한다.
  • 서버는 커넥션 상태를 추적해야 하며 지속적인 커넥션은 특별히 주의해서 다룰 필요가 있다.
  • 비지속적인 커넥션이라면, 서버는 모든 메시지를 전송하고 자신의 커넥션을 닫는다.
  • 지속적인 커넥션이라면, 서버가 Content-Length 헤더를 바르게 계산하기 위해 특별한 주의를 필요로 하는 경우나, 클라이언트가 응답이 언제 끝나는지 알 수 없는 경우에 커넥션은 열린 상태를 유지할 것이다.

7. 로깅

  • 트랙잭션이 완료되면 웹 서버는 트랙잭션이 어떻게 수행되었는지에 대한 로그를 로그파일에 기록한다.
@ruthetum
Copy link
Member

ruthetum commented Aug 21, 2022

현재 webserver 점유율
webserver

  • cloudflare는 CDN, DNS 서비스 제공, 보안 목적으로 많이 활용

@ruthetum
Copy link
Member

[p130, 웹 서버가 하는 일]
5. HTTP 응답만들기
HTTP 응답 만들기 - 올바른 헤더를 포함한 HTTP 응답 메시지를 생성한다.

  • 그러면 web server에서 헤더를 같이 생성하는 것이라고 생각.
  • 단순히 정적 리소스를 서빙할 때는 web server에서 헤더(ex. http status code)를 만드는 것까지는 이해
  • 만약 proxy로 작동하고, 뒷단에 was가 존재할 때는 was에서 전달받은 status code를 그대로 relay하는 것인가? 혹은 해당 status code를 보고 다시 status code를 만드는 것인가?

@ruthetum
Copy link
Member

[CRLF 관련]

  • 왜 CRLF 둘 다 사용하는 것인지.
  • OS에 따라 CRLF를 사용하는 것이 다름
  • CRLF를 모두 사용하게 되면 하나를 사용할 때보다 2바이트를 손해보는 것인데 굳이 사용하는 이유가 있을까? 혹은 둘다 사용하는 windows를 위한 것인지

@ruthetum
Copy link
Member

[Note]

@vo0a
Copy link

vo0a commented Aug 21, 2022

image

  • 다중 I/O 아키텍처에서는 커넥션의 상태가 바뀌면 작은 양의 처리가 수행된다고 알고 있습니다.
  • 그러면, 한 트랜잭션에서 작은 양의 처리가 완료되었지만, 전체 트랜잭션이 완료되지 않은 상태에서 일단 작은 양의 처리가 완료되었으므로 커넥션이 다음번 상태 변경을 위해 커넥션 목록으로 돌아가고, 다른 커넥션을 처리하는 방식으로 될 수 있는 건가요?
  • 실질적으로 한 트랜잭션이 모두 완료 되어야지만 다른 커넥션의 요청을 처리한다면 단일 스레드 I/O랑 다른 점이 무엇인지.. 커넥션을 무시/감지 한다는 차이밖에 없는지 궁금합니다.

@qkrqudcks7 qkrqudcks7 changed the title [2부 5장] 웹서버 [2부 5장] 웹 서버 Aug 23, 2022
@qkrqudcks7
Copy link
Author

qkrqudcks7 commented Aug 24, 2022

[CRLF 관련]

  • 왜 CRLF 둘 다 사용하는 것인지.
  • OS에 따라 CRLF를 사용하는 것이 다름
  • CRLF를 모두 사용하게 되면 하나를 사용할 때보다 2바이트를 손해보는 것인데 굳이 사용하는 이유가 있을까? 혹은 둘다 사용하는 windows를 위한 것인지

The End of the Line Convention

EOL(End-of-Line) 시퀀스에 대한 규약입니다.
옛날부터 os 설계자들 사이에 불일치가 있었습니다. 일부는 CR, 일부는 LF, 일부는 CR-LF 등을 사용했고, 따라서 표준 EOL 시퀀스 규약을 만들었습니다.

텍스트 줄의 끝은 문자 시퀀스 캐리지 리턴 줄 바꿈(CR, LF)으로 표시되어야 합니다. 이 규칙은 송신 및 수신 메커니즘 모두에 적용됩니다.
https://www.quora.com/Why-does-the-HTTP-spec-use-r-n-CR-LF-to-separate-headers-instead-of-n-LF

@qkrqudcks7
Copy link
Author

qkrqudcks7 commented Aug 24, 2022

[p130, 웹 서버가 하는 일] 5. HTTP 응답만들기 HTTP 응답 만들기 - 올바른 헤더를 포함한 HTTP 응답 메시지를 생성한다.

  • 그러면 web server에서 헤더를 같이 생성하는 것이라고 생각.
  • 단순히 정적 리소스를 서빙할 때는 web server에서 헤더(ex. http status code)를 만드는 것까지는 이해
  • 만약 proxy로 작동하고, 뒷단에 was가 존재할 때는 was에서 전달받은 status code를 그대로 relay하는 것인가? 혹은 해당 status code를 보고 다시 status code를 만드는 것인가?

상황에 따라 달라질 수 있습니다

was에서 만든 것을 사용할 수도 있고, webserver에서 만들어서 처리할 수 있습니다.
어떻게 구현하냐에 따라 다릅니다.

@qkrqudcks7
Copy link
Author

image

  • 다중 I/O 아키텍처에서는 커넥션의 상태가 바뀌면 작은 양의 처리가 수행된다고 알고 있습니다.
  • 그러면, 한 트랜잭션에서 작은 양의 처리가 완료되었지만, 전체 트랜잭션이 완료되지 않은 상태에서 일단 작은 양의 처리가 완료되었으므로 커넥션이 다음번 상태 변경을 위해 커넥션 목록으로 돌아가고, 다른 커넥션을 처리하는 방식으로 될 수 있는 건가요?
  • 실질적으로 한 트랜잭션이 모두 완료 되어야지만 다른 커넥션의 요청을 처리한다면 단일 스레드 I/O랑 다른 점이 무엇인지.. 커넥션을 무시/감지 한다는 차이밖에 없는지 궁금합니다.

여기서 의미하는 스레드란?

커널 레벨 스레드를 의미합니다.

단일 스레드 I/O 아키텍처

한 번에 하나씩 req를 처리한다. node.js로 구성한 웹서버는 단일 스레드에 해당합니다.
참고로 node.js는 싱글 스레드라는 한계점 때문에 논 블로킹 I/O를 사용합니다.

다중 I/O 아키텍처

모든 커넥션은 동시에 그 활동을 감시당한다 : 모든 커넥션을 미리 연결시켜 놓는다는 뜻입니다.
미리 모든 커넥션을 연결 시킨 후, 작업이 있을 때만 작업을 처리(작은 양의 처리)하는 방식입니다.

차이점

단일 스레드 방식은 커넥션 연결 -> 작업 수행 -> 커넥션 종료로 매번 커넥션을 연결, 종료해야 하는 수고로움이 있습니다.
하지만 다중 i/o방식은 모든 커넥션 연결 -> 작업 수행 -> 대기 순으로 순수 그 작업만 수행하면 되는 차이가 있습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants