HTTP 클라이언트

HTTP 세션

HTTP 클라이언트가 서버(M2)에 접속하면 HTTP 세션이 생성된다. 클라이언트는 HTTP 세션을 통해 서버에 저장된 여러 콘텐츠를 서비스 받는다. 요청부터 응답까지를 하나의 HTTP 트랜잭션 이라고 부른다. HTTP 세션은 여러 HTTP 트랜잭션을 순차적으로 처리한다.

See also

HTTP 세션 유지정책

M2는 가급적 Apache의 정책을 따른다. 특히 세션유지 정책은 HTTP헤더 값에 따른 변수가 많다. HTTP 세션 유지정책에 영향을 주는 요소는 다음과 같다.

Important

  • 클라이언트 HTTP요청에 명시된 Connection헤더 ( Keep-Alive 또는 Close )

  • 가상호스트 connection 설정

  • 가상호스트 session 설정

  • 가상호스트 keepAlive 설정

  1. 클라이언트 HTTP요청에 Connection: Close 로 명시되어 있는 경우

    GET / HTTP/1.1
    ...(생략)...
    Connection: Close
    

    이같은 HTTP요청에 대해서는 가상호스트 설정여부와 상관없이 Connection: Close 로 응답한다. Keep-Alive 헤더는 명시되지 않는다.

    HTTP/1.1 200 OK
    ...(생략)...
    Connection: Close
    

    이 HTTP 트랜잭션이 완료되면 HTTP 연결을 종료한다.

  2. connection 설정이 close 로 설정된 경우

    # functions.network.http.frontEnd.headers
    
    "connection": {
       "directive": "close"
    }
    

    클라이언트 HTTP요청과 상관없이 Connection: Close 헤더로 응답한다. Keep-Alive 헤더는 명시되지 않는다.

    HTTP/1.1 200 OK
    ...(생략)...
    Connection: Close
    
  3. keepAlivefalse 로 설정된 경우

    # functions.network.http.frontEnd.headers
    
    "connection": {
       "directive": "keep-alive"
    },
    "keepAlive": {
       "enable": false
    }
    

    Keep-Alive 헤더가 명시되지 않는다. HTTP 세션은 지속적으로 재사용가능하다.

    HTTP/1.1 200 OK
    ...(생략)...
    Connection: Keep-Alive
    
  4. keepAlivetrue 로 설정된 경우

    # functions.network.http.frontEnd
    
    "session": {
       "keepAliveSec": 10
    },
    "headers": {
       "connection": {
          "directive": "keep-alive"
       },
       "keepAlive": {
          "enable": true
       }
    }
    

    Keep-Alive 헤더가 명시되며 timeout 값은 세션 Keep-Alive 시간 설정을 사용한다.

    HTTP/1.1 200 OK
    ...(생략)...
    Connection: Keep-Alive
    Keep-Alive: timeout=10
    

    Note

    session.keepAliveSeckeepAlive 의 관계

    keepAlive 설정시 session.keepAliveSec 를 참고하지만 session.keepAliveSec 는 보다 근본적인 문제와 관련이 있다. 성능이나 자원적으로 가장 중요한 이슈는 Idle세션(=HTTP 트랜잭션이 발생되지 않는 세션)의 정리시점을 잡는 것이다. HTTP 헤더 설정은 동적으로 변경되거나 때로 생략될 수 있지만 Idle세션 정리는 훨씬 민감한 문제이다. 이런 이유 때문에 session.keepAliveSeckeepAlive 에 통합되지 않고 별도로 존재한다.

  5. keepAlivemax 속성이 설정된 경우

    # functions.network.http.frontEnd
    
    "session": {
       "keepAliveSec": 10
    },
    "headers": {
       "connection": {
          "directive": "keep-alive"
       },
       "keepAlive": {
          "enable": true,
          "max": 50
       }
    }
    

    Keep-Alive 헤더에 max 값을 명시한다. 이 세션은 max 회 만큼 사용이 가능하며 HTTP 트랜잭션이 진행될때마다 1씩 감소된다.

    HTTP/1.1 200 OK
    ...(생략)...
    Connection: Keep-Alive
    Keep-Alive: timeout=10, max=50
    
  6. keepAlivemax 가 만료된 경우 위의 설정대로 max 가 설정되었다면 max 는 점차 줄어 다음처럼 1까지 도달하게 된다.

    HTTP/1.1 200 OK
    ...(생략)...
    Connection: Keep-Alive
    Keep-Alive: timeout=10, max=1
    

    이 응답은 현재 세션으로 앞으로 1번 HTTP 트랜잭션진행이 가능하다는 의미이다. 이 세션으로 HTTP 요청이 한번 더 진행될 경우 다음과 같이 Connection: Close 헤더로 응답한다.

    HTTP/1.1 200 OK
    ...(생략)...
    Connection: Close
    

HTTP 헤더

성능과 보안상의 이유로 원본서버가 보내는 헤더 중 캐싱과 관련된 표준 헤더만을 선별적으로 인식한다.

Note

어떠한 경우라도 다음 헤더는 캐싱할 수 없다.

  • cookie

  • set-cookie

  • set-cookie2

원본이 응답하는 헤더를 캐싱하기 위해서는 추가 설정이 필요하다.

See also

Cache-Control

HTTP 클라이언트 Cache-Control 헤더 값을 결정한다.

HTTP 압축

원본이 응답한 콘텐츠를 압축하여 전송한다.

acceptEncoding 에 따라 콘텐츠를 구분하도록 설정되어 있어야 한다.

Accept-Encoding: gzip, deflate
../../../_images/compression_1.png

비압축 파일을 실시간으로 압축하여 전송한다.

다음은 파일 크기별 GZIP(Level: 9) 성능 테스트 결과이다.

크기

압축률(%)

처리량

응답속도(ms)

클라이언트 트래픽(Mbps)

원본 트래픽(Mbps)

1KB

26.25

5288

6.72

40.58

55.02

2KB

57.45

5238

7.20

41.52

97.58

4KB

76.94

5236

7.18

42.44

184.04

8KB

87.61

5021

7.53

41.87

337.80

16KB

93.32

4608

8.30

41.19

616.83

32KB

96.26

3495

13.55

34.53

924.22

64KB

97.79

1783

24.50

20.71

938.83

bootstrap.css(20KB)

86.87

3944

9.67

83.79

638.25

bootstrap.min.js(36KB)

73.00

1791

51.50

139.00

514.86

Note

compression 이 활성화되어 있다면 원본 서버로 비압축 콘텐츠만을 요청한다. 비압축 콘텐츠란 원본 서버에 Accept-Encoding 헤더를 명시하지 않고 보냈을 때의 응답을 의미한다. 만약 원본 서버가 비압축 콘텐츠 요청에 대해 Content-Encoding 헤더를 명시했다면 이미 압축된 것으로 간주하여 다시 압축하지 않는다.

HTTP 접근제어

가상호스트 단위로 HTTP 클라이언트 요청에 따라 허용, 거부, 리다이렉트를 수행한다. 접근차단은 보통 ACL(Access Control List)에 차단목록(Black-list)을 작성하지만, 설정편의상 허용목록(White-list)을 작성하기도 한다.

See also

HTTP 라우팅

HTTP 요청을 가상호스트로 라우팅하는 여러 기법에 대해 설명한다.

가상호스트는 보통 원본(Domain 또는 IP목록)과 1:1로 구성되는 것이 기본이다. 하지만 상황에 따라 대표 가상호스트를 여러 하위 가상호스트로 분기하거나, 반대로 독립적인 여러 가상호스트를 하나의 서비스로 포장해야 하는 경우도 발생한다. 각 기능에 따라 클라이언트 통계 / access.log 의 정책이 다를 수 있음을 유의해야 한다.

처리 시점

실서비스에서는 다양한 방식으로 HTTP 요청을 라우팅하는 경우가 발생한다. 각 모듈이 동작하는 시점을 명확히 이해해야 안정적인 운영이 가능하다.

먼저 간단한 HTTP 요청부터 시작하자.

http://foo.com/

이 요청은 아래 그림과 같은 흐름으로 처리된다.

../../../_images/avdhostpoint0.png

HTTP 트랜잭션 은 HTTP 요청을 어플리케이션이 처리하는 단위이다. 따라서 가상호스트에 진입하면서 시작되고, 떠나면서 종료된다.

Note

흔히 HTTP 트랜잭션의 시작을 HTTP Layer로 생각하는데 이는 잘못된 이해이다. HTTP Layer의 책임은 HTTP 프로토콜 구현(Parsing & Reponse)에 한정된다. 파싱된 HTTP 요청이 가상호스트 [foo.com] 로 분기되어야 비로소 HTTP 트랜잭션 이 시작되는 것이다.

URL 전처리HTTP Layer 와 가상호스트 [foo.com] 사이에 위치한다. URL 전처리 를 이용하면 [foo.com] 의 요청을 [bar.com] 으로 분기시킬 수 있다.

../../../_images/avdhostpoint1.png

URL 전처리HTTP 트랜잭션 에 영향을 주지 않는다. [bar.com] 으로 요청이 진입할 때 HTTP 트랜잭션 이 시작된다. [foo.com] 에는 아무런 액션도 발생하지 않는다.

facade 가상호스트 는 통계와 로그를 분리하기 위해 사용한다. [foo.com][bar.com] 의 facade라면 다음과 같이 동작한다.

../../../_images/avdhostpoint2.png

그림에서 알 수 있듯이 HTTP 트랜잭션 이 2개의 가상호스트에서 발생한다. 이렇게 중첩된 경우 상위 HTTP 트랜잭션 이 모든 책임을 위임받는다. 따라서 손쉽게 통계와 로그의 분리가 가능하다.

fallback 가상호스트URL 전처리 와 가상호스트 사이에 존재한다.

../../../_images/avdhostpoint4.png

HTTP 트랜잭션 은 개별 가상호스트에서 독립적으로 이루어진다. fallback 가상호스트 는 HTTP 응답을 가로채 재분기 시키는 메카니즘이다.

Note

URL 전처리fallback 가상호스트 가 같이 사용되는 경우가 종종 있다.

../../../_images/avdhostpoint5.png

fallback 가상호스트URL 전처리 후 분기지점에 위치한다. 따라서 URL은 더 이상 변조되지 않으며, 모든 가상호스트는 변조된 경로를 사용한다.

URL 전처리

정규표현식 을 사용하여 요청된 URL을 변경한다. URL전처리가 설정되어 있다면 모든 클라이언 요청(HTTP 또는 File I/O)은 반드시 URL Rewriter를 거친다.

../../../_images/urlrewrite1.png

URL Rewriter를 통과해야 가상호스트에 갈 수 있다.

See also

만약 URL Rewriter에 의해 접근하려는 Host이름이 변경되었다면 클라이언트 HTTP요청의 Host헤더가 변경된 것으로 간주한다.

facade 가상호스트

hostingaliases 는 가상호스트의 별명만을 추가하는 것이므로 통계와 로그가 분리되지 않는다. 가상호스트는 공유하지만 도메인에 따라 클라이언트 통계access.log 를 분리하고 싶은 경우 Facade가상호스트를 설정한다.

../../../_images/adv_vhost_facade.png

facade는 통계와 로그만 수집한다.

See also

  • modefacadeHost

 {
   "hosting": [
      {
         "name": "example.com"
      },
      {
         "name": "another.com",
         "mode": {
            "facadeHost": "example.com"
         }
      }
   ]
}

예제의 경우 클라이언트 통계access.logexample.com 이 아닌 클라이언트가 요청한 another.com 으로 집계된다.

fallback 가상호스트

콘텐츠가 여러 원본에 분산되어 있다면, fallback 을 활용하여 콘텐츠가 통합되어 있는 것처럼 서비스가 가능하다.

Note

  • 이 기능을 활용하면 콘텐츠 체인 의 위치투명성을 손쉽게 구현할 수 있다.

특히 On-Premise에서 클라우드로 스토리지를 마이그레이션하거나, 스토리지의 용량, 비용 등의 이유로 콘텐츠가 분산되어 있는 환경에서 유용하다.

../../../_images/adv_vhost_link.png

cloud.com에 없는 콘텐츠는 nas.com이 처리한다.

See also

클라이언트 요청이 다른 가상호스트로 위임되더라도 클라이언트 통계access.log 는 클라이언트가 요청한 가상호스트에 기록된다.

Note

fallback 관계에 있는 가상호스트 설정이 다를 경우 의도치 않게 동작할 수 있음을 주의한다. 가상호스트 링크가 A(단순 캐싱) -> B(이미지 압축)로 맺어져 있다면, A에서 처리된 이미지는 압축되지 않지만 B에서 처리된 이미지는 압축된다.

예를 들어 nas.com의 콘텐츠를 cloud.com으로 이전 중일 경우, cloud.com에 없는(= 404 Not Found ) 콘텐츠에 대해서만 nas.com으로 요청을 보낼 수 있다. 아래의 경우 요청이 nas.com에 의해 처리되더라도 클라이언트 통계access.log 는 cloud.com에 기록된다.

{
  "hosting": [
    {
      "name": "cloud.com",
      ... (생략) ...
      "fallbacks" : {
        "enable": true,
        "matchingList": [
          {
            "resCodes": [ "4xx" ],
            "pattern": "/(.*)",
            "replace": "nas.com/#1"
          }
        ]
      }
    },
    {
      "name": "nas.com",
      ... (생략) ...
    }
  ]
}

access.logx-fallback 필드를 통해 클라이언트 요청이 어느 가상호스트에서 처리되었는지 알 수 있다. “-” 는 요청이 링크되지 않았음을 의미하며 “nas.com” 은 해당 요청이 링크되어 nas.com에서 처리되었음을 의미한다.

#Fields: date time s-ip cs-method cs-uri-stem ...(중략)... x-fallback
2016.11.24 16:52:24 220.134.10.5 GET /web/h.gif ...(중략)... -
2016.11.24 16:52:26 220.134.10.5 GET /favicon.ico ...(중략)... nas.com

링크가 여러 번 발생했다면 “+”를 구분자로 링크된 모든 가상호스트가 명시된다. 이 경우 가장 마지막에 위치한 가상호스트가 최종 요청을 처리한 가상호스트이다.

redirect 추적

원본서버에서 Redirect계열(301, 302, 303, 307)로 응답하는 경우 Location 헤더를 추적하여 콘텐츠를 요청한다.

../../../_images/conf_redirectiontrace.png

클라이언트는 Redirect여부를 모른다.

See also