STON Edge Server 완벽 가이드¶
저자: | STON 개발팀 |
---|---|
최신버전: | 2.4.3, 2017년 1월 20일 |
1부. STON 기본: 설정 배우기¶
1장. STON 엣지 서버 (Edge Server)¶
서비스 설계의 원칙¶
서비스의 성공은 가용성, 속도, 확장성에 달려있다. “확장성 웹 아키텍처와 분산 시스템 설계”를 쓴 Kate Matsudaira도 이 세 가지 원칙을 강조한다.
가용성 (availability)
서비스는 항상 가능해야 한다. 장애발생시 90%의 고객은 경쟁사로 이동한다. 완벽한 시스템은 없지만, 장애시 복구는 신속해야 한다.
속도 (speed)
비즈니스에서 시간은 금이다. 느린 응답시간은 매출 감소다. 응답시간이 0.1초 지연되면 매출 1%가 감소한다. Amazon.com의 고객 47%는 웹페이지가 2초 안에 열리기를 원한다.
확장성 (scalability)
고객이 만명이든 백만명이든 서비스는 원활해야 한다. 크기를 키우고 유지하는 노력, 스토리지 확장 용이성, 트랜잭션 처리 여력도 확장성이다. 관리의 확장성도 빠질 수 없다. 진단, 문제 이해, 업데이트와 변경이 쉬워야 한다.
모든 원칙은 최소의 비용으로 지킬수록 효율적이다. 비용은 돈 뿐만이 아니라 시간, 노력, 훈련 등도 포함한다.
성공적인 서비스는 성장 한다. 더 많은 고객과 더 많은 컨텐츠를 감당해야 한다. 성장하면 할수록 원칙들은 더 지키기 어렵다. 어떻게 하면 이 원칙들을 쉽게 최소비용으로 지킬 수 있을까?
서비스의 성장¶
테스트나 파일럿 서비스는 한두대의 서버로 시작한다. 서비스가 조금씩 성장한다. 서버 수는 야금야금 늘어난다. 컨텐츠 갱신은 한 대씩 꼼꼼하게 해야 한다. 손발이 고생할 뿐, 아직까지는 관리에 큰 무리가 없다.
서비스가 성장하기 시작한다. 고객이 늘고, 쌓을 데이터가 점점 커진다. 서버들을 일일이 관리하는 것도 어려워진다. 데이터를 한 곳에 모을 고비용의 스토리지를 도입한다 (NAS, SAN, DAS 등). 고비용이지만 신뢰할 수 있을 것 같다. 컨텐츠 갱신이 쉬워졌다. 스토리지에 올린 컨텐츠는 서버들이 자동으로 가져 간다.
서비스가 가파르게 성장한다. 서버 대수를 늘렸더니 스토리지의 전송 부하가 커졌다. 더 빠른 스토리지는 굉장히 고비용이다. 도입이 망설여 진다. 투자할 가치가 있을까.
동기화 (synchronization) 솔루션을 검토한다. 서버에 데이터 전체를 준비시킬 수는 없다.스토리지에서 컨텐츠를 선별해야 한다. 정확하게 제어하려면 관리 기술이 필수다. 서버 몇 대의 동기화 관리는 쉽다. 그러나 서버와 파일 수가 늘어날 수록 힘들어진다. 갈수록 나빠진다. 커질수록 느려지고 어렵고 불안정하다.
컨텐츠는 계속 변화한다. 추가하고 삭제할 파일이 많아질 수록 동기화 시간은 길어진다. 서비스 규모가 커질 수록, 동기화 관리 시스템도 필연적으로 커지고 복잡해진다. 관리 시스템의 장애는 곧 전체 장애를 일으킨다.
컨텐츠를 빠르고 유연하게 전송할 수 있는 쉬운 방법이 필요하다.
서비스 확장성과 전송¶
계층화 (layering) 로 서비스를 모델링 하면 다음 그림과 같이 두 계층으로 나눌수 있다.

중심에 데이터를 관리하는 스토리지 (storage) 계층이 있다. 그 위에는 서비스 로직이 구현된 어플리케이션 (application) 계층이 있다. 어플리케이션 계층은 소규모 고객용 컨텐츠 전송도 처리할 수 있다. 초기에는 스토리지와 어플리케이션 계층만으로 서비스를 구성할 수 있다.

서비스가 성장하면서 처리비용은 변화한다. 초기에는 로직 개발이, 성장기에는 고객증가와 함께 데이터 관리가 가장 많은 비용을 차지한다. 서비스가 발전할 수록 가장 큰 고민은 컨텐츠 전송 이다. 폭발하는 대역폭을 어떻게 해결할 것인가? 컨텐츠 전송 은 서비스 증설 (Scale-out)의 큰 과제이다.
엣지 (edge) : 전송 계층¶

서비스가 성장할 수록, 전송에 대한 부담은 기하급수적으로 커진다. 쇼핑몰의 컨텐츠 개수는 많게는 수십 억 개에 이른다. 동영상 서비스의 컨텐츠는 TB에 이른지 오래다. 서비스의 증설에는 컨텐츠 전송의 확장성 (scalibility) 을 반드시 고려해야 한다.
엣지(edge)는 서비스의 가장 바깥, 최전방을 가리킨다. 엣지에서 고객은 속도와 가용성을 체험한다. 고객이 요청하는 컨텐츠는 무슨 일이 있어도 ‘반드시’ 전송해야 한다. 고객이 보는 화면에서 깨진 이미지, 심지어 접속불능은 매우 치명적이다. 엣지에서 컨텐츠 전송을 처리하면 어플리케이션과 스토리지의 전송부담은 줄어든다.
엣지의 확장이 쉽고 효율적이면 다른 고비용 계층을 증설할 필요가 없다. 스토리지와 어플리케이션의 증설은 고비용의 비효율적 선택이다.
그렇다면 STON 엣지 서버는 어떻게 컨텐츠 전송을 쉽고 빠르게 바꿀까?
엣지 서버의 동작 방식: 캐시(cache)¶

전송의 규모는 고객의 수와 컨텐츠 크기에 따라 커진다. 얼마나 많은 고객이 어떤 컨텐츠를 요청하는지는 엣지에서 가장 빨리 알 수 있다. 엣지로부터 Bottom-up의 처리흐름이 효율적이다. 따라서 엣지 서버는 고객의 요청에 따라 On-demand 로 동작하는 캐시(cache) 전송방식을 채택하였다. 관리 시스템도 필요없다. 구체적인 동작은 다음과 같다.

엣지 서버는 첫번째 컨텐츠 전송 요청을 받았을 때, 원본 계층으로부터 컨텐츠를 가져와 고객에게 전송한다. 이 컨텐츠를 엣지 서버 자신에게도 저장한다. 두번째 요청 및 그 이후부터는 저장했던 컨텐츠를 고객에게 즉시 전송한다. 저장된 컨텐츠는 미리 설정된 TTL (Time-To-Live) 시간만큼 유효하다.
엣지 서버는 이러한 방식으로 상당한 양의 컨텐츠 전송을 처리할 수 있다. 어플리케이션과 스토리지의 증설을 최소화하면서 빠른 대용량 전송을 처리한다. 성장하는 서비스라면 반드시 엣지를 고려해야 한다.
STON 엣지 서버는 무제약/무조건을 지향하는 소프트웨어다. 어떤 하드웨어에 설치되든 최대 성능을 발휘하도록 설계되었다.
CPU: Many-Core에 최적화되었다. Throughput은 코어개수에 비례한다.
Memory: Memory가 많을수록 빠르게 처리한다. Disk I/O를 절감한다.
Disk: I/O 를 균등 분산한다. 더 많은 데이터를 caching한다.
NIC: 4Gbps NIC Bonding 또는 10Gbps NIC의 Bandwidth를 보장한다.
STON 엣지 서버는 강력한 라이브 모니터링/로그 를 지원한다. 초 단위의 실시간 통계로 지금 당장 서비스 상태가 어떤지 확인할 수 있다. JSON, XML, SNMP 등의 여러 범용포맷으로 실시간 숫자를 제공한다.
STON은 관리자를 위한 쉬운 설정 을 제공한다. STON의 설계이념은 관리자를 위한 엣지 서버다. Web Management 페이지를 통해 직관적인 설정방법을 제공한다. 디테일한 설정을 원할 경우, 단 두 개의 XML 설정 파일로 쉽게 할 수 있다.
엣지 서버의 효과¶
엣지 서버의 효과는 다음과 같다.
- 쉽고 편리한 서비스 가속
- 서비스 원본을 외부로부터 보호 (Origin Shielding)
- 서비스가 핵심적인 역할을 수행할 수 있도록 보조
엣지 서버의 효과는 다음 적용사례를 중심으로도 확인할 수 있다.
Game¶
전통적으로 게임 서비스는 엄청나게 많은 대역폭을 필요로 한다. “대작” 게임부터 간단한 캐주얼 게임까지 범주도 매우 다양하다. 특히 스마트폰 게임의 폭발적 성장과 전파속도는 서비스 형태를 더욱 다양하게 만들었다.

높은 대역폭 출력
단일 서버로 높은 대역폭을 얻는 전통적인 방법은 1Gbps NIC를 본딩(Bonding)하는 것이다. 이를 통해 4Gbps 대역폭까지 얻을 수 있다. 최근 10Gbps NIC도 시장에 많이 보급되는 추세이다.
STON
4Gbps NIC Bonding과 10Gbps NIC에서도 최대 대역폭을 보장한다.사용자 대역폭 보장
모든 사용자는 게임을 빨리 다운로드 받고 싶어한다. 광랜 사용자는 100Mbps의 속도가 얻어지지 않는다면 항의 전화를 걸 것이다. 모두들 빨리 게임을 시작하고 싶어한다. 서버는 물리적으로 대역폭이 꽉 차지 않는 이상 사용자마다의 최대 속도를 균일하게 보장해야 한다.
STON
모든 사용자에게 최대 속도로 전송하는 것을 보장한다.대용량 파일 처리
설치파일이 4GB정도 하는 게임은 이제 대형게임으로도 분류되지도 않는다. 수십 GB는 되어야 “대작”이라는 단어를 달 수 있는 세상이다. 파일이 너무 크면 서버 메모리에 모두 Caching 할 수 없다. 최악의 상황은 파일의 크기가 너무 커서 사용자마다 다운로드 받는 위치가 제각각인 상황이다.
STON
Caching 파일크기 제한이 없다. Memory와 Disk의 적절한 Swap을 통해 언제나 고성능을 보장한다.Range 요청처리
전송 파일이 대형화되는 추세에 따라 Grid Delivery기법의 P2P솔루션도 많이 사용되고 있다. 이런 솔루션의 특징은 파일을 잘게 조각 내어 주고 받기 때문에 서버에 엄청나게 많은 HTTP Range요청을 보낸다. 10GB파일을 만 명의 클라이언트가 서로 다른 Range로 요청하는 상황도 가능하다. 어느 부분을 요청하더라도 서비스는 즉시 가능해야한다. 하지만 원본서버에서는 반드시 원래 파일의 크기만큼만 데이터가 전송되어야 한다.
STON
Range요청에 최적화된 파일 시스템이 탑재되었다. 또한 멀티 다운로드를 통해 빠른 응답성을 보장한다. 원본서버로부터 1Bytes라도 불필요한 다운로드는 하지않는다.
쇼핑몰¶
쇼핑몰은 사이트 접근이 고객의 매출과 직결된다. 이제 전통적인 PC환경 뿐만 아니라 모바일쇼핑이 당연해졌다. 쇼핑환경이 다양해 지는 것 뿐만 아니라 무한히 늘어나는 파일을 관리하지 못한다면 서비스는 곤경에 처한다.

무한대의 작은 파일 “억! 단위를 넘어서는~”, “셀 수 없이 많은~”, “언제나 늘어나기만 하는~” 파일을 저장하기 위해서는 고가의 Storage가 필요하다. 하지만 경제성이 중요한 Edge서버에서는 그럴 수 없다. 크기가 1KB인 파일이 10억 개 존재하는 서비스도 있을 수 있다. 결론적으로 모든 파일을 Caching할 수 없다. 원본서버의 부하를 최소화하면서도 접근 빈도가 높은 파일을 항상 유지하는 방법이 필요하다.
STON
메모리와 Disk 자원의 최대용량만큼 Caching한다. 모든 파일의 접근 빈도는 실시간으로 관리되며 LRU(Least Recently Used) 에 의해 오래된 파일 순으로 삭제된다.많은 사용자
쇼핑몰은 많은 사용자를 동시에 처리할 수 있어야 한다. 급작스러운 이벤트에 의해 사용자 접속이 폭발적으로 증가(=Burst)하기도 한다. Burst 시 서버는 스스로를 보호해야 하며 Burst 후에도 안정성을 유지해야 한다.
STON
CPU 확장성(Scalability. 자원의 증설에 따라 솔루션의 성능이 높아지는 것)을 보장한다. 탄력적인 HTTP Keep-Alive 처리와 소켓관리를 통해 Burst시에도 안정성을 보장한다.반응성
쾌적한 쇼핑환경이란 페이지가 빠르게 로딩되는 것을 의미한다. 사용자는 기다리지 않는다. 3초 안에 로딩되지 않으면 다른 사이트로 떠난다. 일반적으로 메인 페이지는 100개 내외의 파일로 이루어지며 물리적 환경을 고려하더라도 통상 1초 대에 페이지는 완벽하게 로딩되어야 한다.
STON
실시간 파일 인덱싱을 통한 즉시 응답을 보장한다. 부드러운 파일교체를 통해 원본 종속성 없이 반응성을 극대화할 수 있다. 모든 HTTP 응답(First byte 응답, 트랜잭션 완료)에 대해 로그와 통계수치를 제공하여 성능저하 여부를 실시간으로 검출할 수 있다.페이지 TTL
대다수의 사용자의 이동 경로는 메인 페이지 -> 대형 카테고리 페이지 -> 소형 카테고리 -> 상세 페이지 순이다. 페이지마다 노출 빈도가 다를 뿐만 아니라 갱신 주기도 달라야 한다. 스마트한 페이지 Caching & 갱신 방법이 필요하다.
STON
URL마다 별도의 TTL을 부여할 수 있다. 또한 Purge, Expire, ExpireAfter, HardPurge 등 상황에 맞는 다양한 방식의 갱신 방법을 제공한다.
미디어¶
미디어 전용 프로토콜은 점차 설 자리를 잃어가고 있다. HTTP, MP4의 간단하지만 강력한 조합은 점차 세력을 넓혀가고 있다. 모바일의 가변적인 연결상태를 고려 한다면 HTTP 기반의 Streaming방식이 전송 표준이 될 것이다.

미디어 인식
더 이상 파일을 Chunk로 인식해서는 안된다. 미디어 파일을 정확히 인식할 수 있어야만 대역폭 절감과 함께 다양한 부가기능을 연동할 수 있다. 서버가 파일 해석을 위해서 파일의 모든 부분을 필요로 한다면 사용자는 영상재생을 포기할 것이다.
STON
MP4, MP3, M4A, FLV 포맷을 지원한다. 다운로드와 동시에 HTTP Pseudo Streaming을 위해 필요한 영역을 우선적으로 Caching한다.미디어 헤더 재배치
헤더가 뒤에 있는 파일의 경우 HTTP Pseudo Streaming이 불가능하다. 이를 위해서는 전용 플레이어가 필요하지만 이는 사용자에게 짜증을 +10한다.
STON
MP4파일 인코딩 후 헤더가 뒤에 붙는다면 헤더를 앞으로 옮겨주는 작업을 추가적으로 수행해야 한다. STON은 자연스럽게 헤더를 앞으로 옮겨 서비스 한다.대역폭 조절
대부분의 영상을 끝까지 보는 사용자는 드물다. 그러므로 재생에 무리가 없도록 필요한 만큼만 대역폭을 사용하는 것이 효율적인 전송방법이다. 같은 영상이더라도 360p, 480p, 720p, 1080p처럼 Bitrate를 다양하게 서비스 한다.
STON
Bandwidth-Throttling을 통하여 미디어 파일의 전송 대역폭을 최적화할 수 있다.구간추출
미리보기/하이라이트/공유하기 등 파일 전체가 아닌 특정 구간만을 서비스하는 경우도 많다. 서비스하는 모든 파일에 대해 구간을 추출하는 것은 시간과 저장공간을 지나치게 낭비한다. 심지어 사용자마다 추출 구간이 다른 경우도 있다. 또한 Skip기능을 구간 재생으로 구현하는 플레이어도 존재한다.
STON
Trimming기능을 통해 구간을 추출하여 완전한 형태의 미디어 파일로 서비스한다.
뉴스 / 커뮤니티¶
아주 높은 충성도의 사용자층을 확보한 사이트는 흥미로운 점이 많다. 같은 관심사를 가지는 사용자들이 모이기 때문에 교류가 활발하며 페이지에 머무르는 시간도 매우 길다. 서비스 패턴이 제각각이라 서비스하기 꽤 까다롭다.

304 Not Modified
사이트 충성도가 매우 높기 때문에 이미 대부분의 파일을 사용자 로컬에 저장하고 있다. 때문에 실제로 전송되는 파일보다 “변경확인” 비율이 압도적이다.
STON
자주 접근되는 파일은 항상 메모리에 상주하도록 보장한다. “변경확인” 작업은 기다림 없이 즉시 처리된다.Bypass
사용자에 특화된 페이지나 새로운 글, 리플 등 페이지는 항상 Caching할 수 없는 영역을 포함한다. 하지만 Domain을 별도로 나누지 않고 단일 도메인을 Reverse-Proxy에 위임하는 경우가 많다.
STON
다양한 조건을 기반으로 바이패스 대상을 정교하게 분류한다. 또한 Origin Affinity, Private 기능을 이용해 로그인 세션을 유지할 수 있다.불안한 원본
중, 소형 기업 또는 개인이 운영하는 사이트들은 고가의 장비나 인프라, 인력을 운영하기 어렵다. 원본서버 장애 빈도가 상대적으로 높으며 이를 극복하기 위한 경제성은 매우 나쁘다.
STON
원본서버 과부하 또는 장애를 판단하여 자동으로 배제/복구가 이루어진다. 원본서버 장애 시 TTL을 자동으로 연장시켜 원본서버 의존성을 최소화한다.이미지 가공
같은 이미지를 사용자 환경에 따라 다양하게 보여줄 필요가 있다. 검색 결과에서는 Thumbnail 이미지를, 뉴스 사이트에서는 “XX 뉴스” 같은 글씨를 워터마크로 표시해야한다. 같은 이미지를 보여지는 형태에 따라 매번 가공하는 것은 저장공간과 시간, 인력의 낭비다.
STON
dims 기능을 사용하면 원본서버에 단 하나의 이미지 만으로 원하시는 형태를 URL 호출만으로 생성할 수 있다.
파일기반 서버¶
Edge는 Reverse-Proxy구조에 기반한다. Reverse-Proxy의 핵심 개념은 원격서버에 있는 파일을 로컬에 복제/갱신/관리하는 것이다. 이미 검증된 STON을 서비스 서버와 연동할 수 있다면 Storage중앙 집중화 및 동기화 이슈를 제거할 수 있다. 뿐만 아니라 개발시간 단축과 서비스 신뢰도 향상의 두마리 토끼를 모두 잡을 수 있다.

File I/O 지원
전용 프로토콜이 필요하다면 해당 모듈에 종속적인 서버가 되어 버린다. 힘들게 연동했다 하더라도 성능이 떨어지면 무용지물이다. 모듈과 서버 사이의 중간 단계는 최소화되어야 한다.
STON
표준 File I/O로 STON이 연동된다. 전용서버와 STON사이에는 Linux Kernel(VFS)만이 존재하여 고성능을 보장한다.Web Server 연동
표준 Web 서버(Apache, Lighttpd, NginX)에 특화된 확장모듈이 설치된 경우 표준 Reverse-Proxy를 도입하기 힘들 수 있다. DB/WAS와 연동되는 파일 서비스 또는 과금/결제 서비스 같은 경우 쉽게 서비스를 확장하기 어렵다.
STON
Apache의 DocumentRoot를 STON으로 지정하면 Apache는 STON을 물리적 디스크로 인식한다. 더 설정할 것은 없다.Wowza 연동
미디어서비스에서는 Wowza가 사실상의 표준이다. 하지만 Wowza의 HTTP Caching기능은 사용하기 번거로울 뿐만 아니라 빈약하다. 또한 점차 HTTP 이외의 “전용” 프로토콜은 사라지는 추세이다.
STON
로컬 디스크로 Mount할 수 있을 뿐만 아니라 MP4헤더 변환, Trimming등 모든 기능을 사용할 수 있다.리소스 제약
Back-end에 존재하는 파일을 Front-End의 사용자에게 전달하는 서버라면 항상 파일 동기화가 문제된다. 게임서버, SNS서버 등 전용서버의 개발 이슈는 항상 존재한다. 이런 서버의 경우 중단 없이 장기간 운영 되야 하므로 메모리, 디스크 사용이 엄격하게 제한되어야 한다.
STON
최대 메모리, 디스크 사용량을 제한할 수 있다. 또한 디스크로 Mount하여도 다른 모든 기능은 동일하게 동작하여 복합적인 서비스를 최소한의 솔루션으로 구성할 수 있다.
STON은 이러한 특성들을 적극 활용하는 다음 서비스들과 함께 성장하고 있다.

2장. 시작하기¶
이장에서는 시스템 구성으로부터 설치 그리고 예제 가상호스트까지 구성해본다. 텍스트 편집기만 있으면 누구나 할 수 있다.
STON은 표준 Linux 서버에서 동작하도록 개발되었다. 개발 단계부터 HW뿐만 아니라 OS, 파일시스템 등 종속성을 가질 수 있는 요소는 최대한 배제하였다. 고객이 합리적인 장비를 선택할 수 있도록 돕는 것은 매우 중요하다. 왜냐하면 서비스의 특성과 규모에 따라 적절한 서버를 구성하는 것이 서비스의 시작이기 때문이다.
서버 구성¶
일반적으로 서버를 구성할 때는 CPU, 메모리, 디스크를 주로 고려한다. 10Gbps급의 높은 성능를 요구하는 서비스라면 각 구성요소가 서비스 특성을 만족해야 원하는 성능을 얻을 수 있다.
CPU
Quad 코어 이상을 권장한다. STON은 Many-Core에 대해 확장성(Scalability)를 가진다. 코어가 많으면 많을수록 초당 처리량은 증가한다. 단, 높은 처리량이 반드시 높은 트래픽을 의미하는 것은 아니다.
클라이언트가 많을수록 많은 CPU는 힘이 된다.
4KB인 파일을 약 26만번을 전송하는 것과 1GB파일을 한번 전송하는 것은 같은 대역폭을 사용한다. CPU선택의 가장 큰 기준은 얼마나 많은 동시접속을 처리하는가이다.
메모리
Memory-Indexing 방식을 사용하므로 4GB이상을 권장한다. ( 메모리 구조 참조) 자주 접근되는 콘텐츠는 항상 메모리에 상주하지만 그렇지 않은 컨텐츠는 디스크에서 로딩한다. 따라서 컨텐츠가 많고 집중도가 낮다면(Long-tail) 디스크 부하 증가로 성능이 저하될 수 있다. 서비스되는 콘텐츠 개수와 상관없이 콘텐츠 크기가 커서 디스크 I/O 부하가 높다면 메모리를 증설하여 부하를 낮출 수 있다.
디스크
OS를 포함하여 최소 3개 이상을 권장한다. 디스크 역시 많으면 많을수록 많은 콘텐츠를 캐싱할 수 있을뿐만 아니라 I/O부하도 분산된다.
항상 OS와 STON은 콘텐츠와 별도의 디스크로 구성한다.
일반적으로 OS가 설치된 디스크에 STON을 설치한다. 로그 역시 같은 디스크에 구성하는 것이 일반적이다. 로그는 서비스 상황을 실시간으로 기록하기 때문에 항상 Write부하가 발생한다.
STON은 디스크를 RAID 0처럼 사용한다. 성능와 RAID의 상관여부는 고객 서비스 특성에 따라 달라진다. 하지만 파일 변경이 빈번하지 않고 콘텐츠의 크기가 물리적 메모리 크기보다 훨씬 큰 경우 RAID를 통한 Read속도 향상이 효과적일 수 있다.
OS 구성¶
가장 기본적인 형태로 설치한다. 표준 64bit Linux 배포판(Cent 6.2이상, Ubuntu 10.04이상) 이라면 정상동작한다. 패키지 의존성을 가지지 않는다.
설치¶
최신버전의 STON을 다운로드 받는다.
[root@localhost ~]# wget http://foobar.com/ston/ston.2.0.0.rhel.2.6.32.x64.tar.gz --2014-06-17 13:29:14-- http://foobar.com/ston/ston.2.0.0.rhel.2.6.32.x64.tar.gz Resolving foobar.com... 192.168.0.14 Connecting to foobar.com|192.168.0.14|:80... connected. HTTP request sent, awaiting response... 200 OK Length: 71340645 (68M) [application/x-gzip] Saving to: “ston.2.0.0.rhel.2.6.32.x64.tar.gz” 100%[===============================================>] 71,340,645 42.9M/s in 1.6s 2014-06-17 13:29:15 (42.9 MB/s) - “ston.2.0.0.rhel.2.6.32.x64.tar.gz” saved [71340645/71340645]
압축을 해지한다.
[root@localhost ~]# tar -zxf ston.2.0.0.rhel.2.6.32.x64.tar.gz
설치 스크립트를 실행한다.
[root@localhost ~]# ./ston.2.0.0.rhel.2.6.32.x64.sh
설치과정은 install.log에 기록된다. 로그를 통해 설치 중 발생하는 문제를 알 수 있다.
#DownloadURL: http://foobar.com/ston/ston.2.0.0.rhel.2.6.32.x64.tar.gz #DownloadTime: 13 sec #Target: STON 2.0.0 #Date: 2014.03.03 16:48:35 Prepare for STON 2.0.0 install process Stopping STON... STON stopped [Copying files] `./fuse.conf' -> `/etc/fuse.conf' `./libfuse.so.2' -> `/usr/local/ston/libfuse.so.2' `./libtbbmalloc_proxy.so' -> `/usr/local/ston/libtbbmalloc_proxy.so' `./start-stop-daemon' -> `/usr/sbin/start-stop-daemon' `./libtbbmalloc_proxy.so.2' -> `/usr/local/ston/libtbbmalloc_proxy.so.2' `./libtbbmalloc.so' -> `/usr/local/ston/libtbbmalloc.so' `./libtbbmalloc.so.2' -> `/usr/local/ston/libtbbmalloc.so.2' `./libtbb.so' -> `/usr/local/ston/libtbb.so' `./libtbb.so.2' -> `/usr/local/ston/libtbb.so.2' `./stond' -> `/usr/local/ston/stond' `./stonx' -> `/usr/local/ston/stonx' `./stonr' -> `/usr/local/ston/stonr' `./stonu' -> `/usr/local/ston/stonu' `./stonapi' -> `/usr/local/ston/stonapi' `./server.xml.default' -> `/usr/local/ston/server.xml.default' `./vhosts.xml.default' -> `/usr/local/ston/vhosts.xml.default' `./ston_format.sh' -> `/usr/local/ston/ston_format.sh' `./ston_diskinfo.sh' -> `/usr/local/ston/ston_diskinfo.sh' `./wm.sh' -> `/usr/local/ston/wm.sh' [Exporting config files] #Export so directory /usr/local/ston/ to ld.so.conf #Export sysctl to /etc/sysctl.conf vm.swappiness=0 vm.min_free_kbytes=524288 #Export sudoers for WM Defaults !requiretty winesoft ALL=NOPASSWD: /etc/init.d/ston stop, /etc/init.d/ston start, /bin/ps -ef [Configuring STON daemon script] STON deamon activate in run-level 2345. [Installing sub-packages] curl installed. libjpeg installed. libgomp installed. rrdtool installed. [Installing WM] Stopping WM... WM stopped `./wm.server_default.xml' -> `/usr/local/ston/wm/tmp/conf/server_default.xml' `./wm.vhost_default.xml' -> `/usr/local/ston/wm/tmp/conf/vhost_default.xml' WM configuration found. Current WM port : 8500 PHP module for Legacy(CentOS 5.5) installed `./libphp5.so.5.5' -> `/usr/local/ston/wm/modules/libphp5.so' WM installation almost complete. Changing WM privileges. Installation successfully complete
라이선스 발급¶
신규 고객의 경우 다음 절차를 통해 라이선스를 발급한다.
- 신청양식 작성
- license@winesoft.co.kr 로 전송
- 확인절차 후 발급
라이선스 파일(license.xml)이 반드시 설치경로에 존재해야 STON이 정상적으로 구동된다.
업데이트¶
최신버전이 배포되면 stonu명령어로 업데이트할 수 있다.
./stonu 2.0.1
또는 13장. WM (Web Management) 의 최신버전 업데이트 를 통해 간편하게 업데이트를 진행할 수 있다.
실행하기¶
보통 기본경로에 STON을 설치한다.
/usr/local/ston/
다음 파일 중 하나라도 존재하지 않거나 XML문법에 맞지 않을 경우 실행되지 않는다.
- license.xml
- server.xml
- vhosts.xml
최초 설치시 모든 XML파일이 존재하지 않는다. 배포받은 라이센스파일을 설치 경로에 복사한다. 그리고 설치경로의 server.xml.default와 vhosts.xml.default를 복사 또는 수정하여 설정하길 바란다. *.default파일은 항상 최신패키지와 함께 배포된다.
Hello World¶
vhosts.xml 파일을 열어 다음과 같이 편집한다.
<Vhosts>
<Vhost Name="www.example.com">
<Origin>
<Address>hello.winesoft.co.kr</Address>
</Origin>
</Vhost>
</Vhosts>
STON 실행¶
발급받은 license.xml을 설치 경로에 복사한다.
server.xml을 열어 <Storage>를 구성한다.
<Server> <Cache> <Storage> <Disk>/cache1/</Disk> <Disk>/cache2/</Disk> </Storage> </Cache> </Server>
주석
STON은 기본적으로 디스크를 저장공간으로 사용하기 때문에 디스크가 설정되어 있지 않으면 구동되지 않는다. 자세한 내용은 다음 장에서 설명한다.
STON을 실행한다.
[root@localhost ~]# service ston start
STON을 중지하고 싶다면 stop 명령을 사용한다.
[root@localhost ~]# service ston stop
가상호스트 동작확인¶
(Windows 7 기준) C:\Windows\System32\drivers\etc\hosts 파일에 다음과 같이 www.example.com 도메인을 설정한다.
192.168.0.100 www.example.com
브라우저로 www.example.com에 접근했을 때 다음 페이지가 정상적으로 서비스되면 성공입니다.
WM이 느리거나 그래프가 나오지 않는 문제¶
설치과정 중 RRD그래프는 동적으로 다운로드 받아서 설치된다. 제한된 네트워크에서 STON을 설치할 경우 RRD가 제대로 설치되지 않을 수 있다. 이로 인해 13장. WM (Web Management) 이 매우 느리게 동작하거나 Appendix A: Graph 가 동작하지 않게 된다. 다음과 같이 수정한다.
1. rrdtool 설치확인
다음과 같이 설치여부를 확인한다.
[root@localhost ston]# yum install rrdtool Loaded plugins: fastestmirror, security Loading mirror speeds from cached hostfile * base: centos.mirror.cdnetworks.com * elrepo: ftp.ne.jp * epel: mirror.premi.st * extras: centos.mirror.cdnetworks.com * updates: centos.mirror.cdnetworks.com Setting up Install Process Package rrdtool-1.3.8-6.el6.x86_64 already installed and latest version Nothing to do다음은 Ubuntu계열의 경우이다.
root@ubuntu:~# apt-get install rrdtool Reading package lists... Done Building dependency tree Reading state information... Done rrdtool is already the newest version. The following packages were automatically installed and are no longer required: libgraphicsmagick3 libgraphicsmagick++3 libgraphicsmagick1-dev libgraphics-magick-perl libgraphicsmagick++1-dev Use 'apt-get autoremove' to remove them. 0 upgraded, 0 newly installed, 0 to remove and 102 not upgraded.
2. RRD 수동설치
만약 rrdtool이 yum을 이용해서 설치가 되지 않는다면, OS 버전에 맞는 패키지를 다운로드 후 수동으로 설치한다.
Name | Last Modified | Size | Description |
---|---|---|---|
tcl-rrdtool-1.4.7-1.el5.rf.i386.rpm | 06-Apr-2012 16:57 | 36K | RHEL5 and CentOS-5 x86 32bit |
tcl-rrdtool-1.4.7-1.el5.rf.x86_64.rpm | 06-Apr-2012 16:57 | 37K | RHEL5 and CentOS-5 x86 64bit |
tcl-rrdtool-1.4.7-1.el6.rfx.i686.rpm | 06-Apr-2012 16:57 | 35K | RHEL6 and CentOS-6 x86 32bit |
tcl-rrdtool-1.4.7-1.el6.rfx.x86_64.rpm | 06-Apr-2012 16:57 | 35K | RHEL6 and CentOS-6 x86 64bit |
원본서버¶
가상호스트는 원본서버를 대신해 콘텐츠를 서비스하는 것이 목적이다. 서비스 형태에 맞게 다양한 원본서버는 다양하게 접근이 가능하다.
<Vhosts>
<Vhost Name="www.example.com">
<Origin>
<Address>1.1.1.1</Address>
<Address>1.1.1.2</Address>
</Origin>
</Vhost>
</Vhosts>
<Address>
가상호스트가 콘텐츠를 복제 할 원본서버 주소. 개수제한은 없다. 주소가 2개 이상일 경우 Active/Active방식(Round-Robin)으로 선택된다. 원본서버 주소 포트가 80인 경우 생략할 수 있다.
예를 들어 다른 포트(8080)로 서비스되는 경우 1.1.1.1:8080과 같이 포트번호를 명시해야 한다. 주소는 {IP|Domain}{Port}{Path}형식으로 8가지 형식이 가능하다.
Address | Host헤더 |
---|---|
1.1.1.1 | 가상호스트명 |
1.1.1.1:8080 | 가상호스트명:8080 |
1.1.1.1/account/dir | 가상호스트명 |
1.1.1.1:8080/account/dir | 가상호스트명:8080 |
example.com | example.com |
example.com:8080 | example.com:8080 |
example.com/account/dir | example.com |
example.com:8080/account/dir | example.com:8080 |
원본요청 기본 Header 중 Host헤더를 별도로 설정하지 않는한 표의 Host헤더를 전송한다.
<Vhosts>
<Vhost Name="www.example.com">
<Origin>
<Address>origin.com:8888/account/dir</Address>
</Origin>
</Vhost>
</Vhosts>
예를 들어 위와같이 설정하면 원본으로 다음과 같이 요청한다.
GET / HTTP/1.1
Host: origin.com:8888
보조 원본주소¶
보조 원본서버를 설정한다.:
<Vhosts>
<Vhost Name="www.example.com">
<Origin>
<Address>1.1.1.1</Address>
<Address>1.1.1.2</Address>
<Address2>1.1.1.3</Address2>
<Address2>1.1.1.4</Address2>
</Origin>
</Vhost>
</Vhosts>
<Address2>
모든
<Address>
가 정상동작하고 있다면<Address2>
는 서비스에 투입되지 않는다. Active서버에 장애가 감지되면 해당 서버를 대체하기 위해 투입되며 Active서버가 복구되면 다시 Standby상태로 돌아간다. 만약 Standby서버에 장애가 감지되면 해당 Standby서버가 복구되기 전까지 서비스에 투입되지 않는다.
API 호출¶
HTTP기반의 API를 제공한다. API 호출권한은 관리자 설정 의 영향을 받는다. 허가되지 않았다면 곧바로 연결을 종료한다.
STON버전을 확인한다.
http://127.0.0.1:10040/version
같은 API를 Linux Shell에서 명령어로 수행한다.
./stonapi version
하드웨어 정보조회¶
하드웨어 정보를 조회한다.
http://127.0.0.1:10040/monitoring/hwinfo
결과는 JSON형식으로 제공된다.
{
"version": "1.1.9",
"method": "hwinfo",
"status": "OK",
"result":
{
"OS" : "Linux version 3.3.0 ...(생략)...",
"STON" : "1.1.9",
"CPU" :
{
"ProcCount": "4",
"Model": "Intel(R) Xeon(R) CPU E5606 @ 2.13GHz",
"MHz": "1200.000",
"Cache": "8192 KB"
},
"Memory" : "8 GB",
"NIC" :
[
{
"Dev" : "eth1",
"Model" : "Intel Corporation 82574L Gigabit Network Connection",
"IP" : "192.168.0.13",
"MAC" : "00:25:90:36:f4:cb"
}
],
"Disk" :
[
{
"Dev" : "sda",
"Model" : "HP DG0146FAMWL (scsi)",
"Total" : "238787584",
"Usage" : "40181760"
},
{
"Dev" : "sdb",
"Model" : "HITACHI HUC103014CSS600 (scsi)",
"Total" : "144706478080",
"Usage" : "2101075968"
},
{
"Dev" : "sdc",
"Model" : "HITACHI HUC103014CSS600 (scsi)",
"Total" : "144706478080",
"Usage" : "2012160000"
}
]
}
}
재시작/종료¶
명령어를 통해 STON을 재시작/종료할 수 있다. 의도하지 않은 결과를 피하기 위해 웹 페이지를 통한 확인작업이 반드시 필요하도록 개발되었다.
http://127.0.0.1:10040/command/restart
http://127.0.0.1:10040/command/restart?key=JUSTDOIT // 즉시 실행
http://127.0.0.1:10040/command/terminate
http://127.0.0.1:10040/command/terminate?key=JUSTDOIT // 즉시 실행
Caching 초기화¶
서비스를 중단하며 캐싱된 모든 컨텐츠를 삭제한다. 설정된 모든 디스크를 포맷하며 작업이 완료되면 다시 서비스를 재개한다.
http://127.0.0.1:10040/command/cacheclear
http://127.0.0.1:10040/command/cacheclear?key=JUSTDOIT // 즉시 실행
콘솔에서는 다음 명령어를 통해 전체 또는 하나의 가상호스트를 초기화한다.
./stonapi reset
./stonapi reset/ston.winesoft.co.kr
3장. 설정구조¶
이 장에서는 설정구조와 변경된 설정을 적용하는 방법에 대해 설명한다. 구조를 정확히 이해해야 빠르게 서버를 배치할 수 있을뿐만 아니라 장애상황을 유연하게 극복할 수 있다.
설정은 크게 전역(server.xml)과 가상호스트(vhosts.xml)로 나뉜다.
![]()
2개의 .xml파일이 전부입니다.
2개의 XML파일로 대부분의 서비스를 구성한다. 여러 TXT파일에는 가상호스트별 예외조건을 설정하는데, 특정기능의 목록을 작성하는데 사용된다. 기능설명을 위해 다음처럼 완전한 형태의 XML을 예시하는 것은 굉장히 번거롭다.
<Server>
<VHostDefault>
<Options>
<CaseSensitive>ON</CaseSensitive>
</Options>
</VHostDefault>
</Server>
때문에 다음과 같이 축약하여 설명한다.
# server.xml - <Server><VHostDefault><Options>
<CaseSensitive>ON</CaseSensitive>
주석
라이센스(license.xml)는 설정이 아니다.
설정 Reload¶
설정 변경 후 관리자가 명확하게 API를 호출해야 한다. 시스템과 성능 관련설정을 제외한 대부분의 설정은 서비스 중단없이 즉시 적용된다.
http://127.0.0.1:10040/conf/reload
설정이 변경될 때마다 Info 로그 에 변경사항이 기록된다.
server.xml 전역설정¶
실행파일과 같은 경로에 존재하는 server.xml이 전역설정 파일이다. XML형식의 텍스트파일이다.
# server.xml
<Server>
<Host> ... </Host>
<Cache> ... </Cache>
<VHostDefault> ... </VHostDefault>
</Server>
우선 전역설정의 구조와 간단한 기능위주로 설명한다. 15장. 접근제어 나 11장. SNMP 등 전역설정에 위치하지만 덩치가 큰 기능들에 대해서는 각 주제를 다루는 장에서 설명한다.
관리자 설정¶
관리목적의 기능을 설정한다.
# server.xml - <Server>
<Host>
<Name>stream_07</Name>
<Admin>admin@example.com</Admin>
<Manager Port="10040" HttpMethod="ON" Role="Admin" UploadMultipartName="confile">
<Allow>192.168.1.1</Allow>
<Allow Role="Admin">192.168.2.1-255</Allow>
<Allow Role="User">192.168.3.0/24</Allow>
<Allow Role="Looker">192.168.4.0/255.255.255.0</Allow>
</Manager>
</Host>
<Name>
서버 이름을 설정한다. 이름이 입력되지 않으면 시스템 이름이 사용한다.
<Admin>
관리자 정보(메일 또는 이름)를 설정한다. 이 항목은 SNMP 조회목적으로만 사용된다.
<Manager>
관리용도로 사용할 매니저 포트와 ACL(Access Control List)을 설정한다. ACL은 IP, IP범위, BitMask, Subnet 이상 네 가지 형식을 지원한다. 접속한 세션이 Allow로 접근이 허가된 IP가 아니면 접속을 차단한다. API를 호출하는 IP가
<Allow>
목록에 반드시 설정되어야 한다.접근조건에 따라 접근권한(Role)을 설정할 수 있다. 접근권한이 없는 요청에 대해서는 401 Unauthorized 로 응답한다.
<Allow>
조건에Role
속성을 명시적으로 선언하지 않을 경우<Manager>
의Role
속성이 적용된다.Admin
모든 API호출이 가능하다.User
api_monitoring , Appendix A: Graph API만 호출할 수 있다.Looker
Appendix A: Graph API만 호출할 수 있다.
기타 다음과 같은 자잘한 관리목적의 속성을 가진다.
HttpMethod
ON (기본)
api-etc-httpmethod 호출시 ACL을 검사한다.OFF
api-etc-httpmethod 호출시 ACL을 검사하지 않는다.
UploadMultipartName
설정 업로드 의 변수명을 설정한다.
Storage 구성¶
Caching된 콘텐츠를 저장할 Storage를 구성한다.
# server.xml - <Server>
<Cache>
<Storage DiskFailSec="60" DiskFailCount="10" OnCrash="hang">
<Disk>/user/cache1</Disk>
<Disk>/user/cache2</Disk>
<Disk Quota="100">/user/cache3</Disk>
</Storage>
</Cache>
<Storage>
콘텐츠를 저장할 디스크를 설정한다. 하위
<Disk>
개수제한은 없다.디스크는 장애가 가장 많이 발생하는 장비이기 때문에 명확한 장애조건을 설정할 것을 권장한다.
DiskFailSec (기본: 60초)
동안DiskFailCount (기본: 10)
만큼 디스크 작업이 실패하면 해당 디스크는 자동으로 배제된다. 배제된 디스크 상태는 “Invalid”로 명시된다.모든 디스크가 배제될 수도 있는데 이 때의 동작방식은
OnCrash
속성으로 설정한다.hang (기본)
장애 디스크를 모두 재투입한다. 정상 서비스를 기대한다기 보다는 원본을 보호하려는 목적이 강하다.bypass
모든 요청을 원본서버로 바이패스 한다. 디스크가 복구되면 즉시 STON이 서비스를 처리한다.selfkill
STON을 종료시킨다.
각 디스크마다 최대 캐싱용량을 Quota (단위: GB)
속성으로 설정할 수 있다.
굳이 설정하지 않더라도 항상 디스크가 꽉 차지 않도록 LRU(Least Recently Used) 알고리즘에 의해 오래된 콘텐츠를 자동으로 삭제한다.
특별히 호환성에 문제가 있는 파일시스템은 없다. 그러므로 관리자가 친숙한 파일 시스템을 사용해도 성능에 큰 영향은 없다.
메모리 제한¶
사용할 최대 메모리와 컨텐츠 적재비율 설정한다.
# server.xml - <Server>
<Cache>
<SystemMemoryRatio>100</SystemMemoryRatio>
<ContentMemoryRatio>50</ContentMemoryRatio>
</Cache>
<SystemMemoryRatio> (기본: 100%)
시스템 메모리에서 STON이 사용할 최대 메모리를 비율로 설정한다. 예를 들어 16GB장비에서 이 수치를 50(%)으로 설정하면 시스템 메모리가 8GB인 것처럼 동작한다. 특히 18장. File System 등을 통해 다른 프로세스와 연동할 때 유용하다.
<ContentMemoryRatio> (기본: 50%)
STON은 디스크에서 로딩된 Body 데이터를 메모리에 최대한 Caching하여 서비스 품질을 향상시킨다. 서비스 형태에 따라 이 비율을 조절하여 품질을 최적화한다.
ContentMemoryRatio를 통해 메모리비율을 설정한다.
예를 들어 게임 다운로드처럼 파일 개수는 많지 않지만 Contents크기가 큰 서비스의 경우 File I/O 부하가 부담스럽다. 이런 경우
<ContentMemoryRatio>
를 높여서 보다 많은 Contents데이터가 메모리에 상주할 수 있도록 설정하면 서비스 품질을 높일 수 있다.ContentMemoryRatio를 높이면 I/O가 감소한다.
기타 Caching 설정¶
기타 Caching서비스의 기반동작을 설정한다.
# server.xml - <Server>
<Cache>
<Cleanup>
<Time>02:00</Time>
<Age>0</Age>
</Cleanup>
<Listen>0.0.0.0</Listen>
<ConfigHistory>30</ConfigHistory>
</Cache>
<Cleanup>
하루에 한 번 시스템 최적화를 수행한다. 최적화의 대부분은 디스크정리 작업으로 I/O 부하가 발생한다. 서비스 품질저하를 방지하기 위해 최적화는 조금씩 점진적으로 수행된다.
<Time> (기본: AM 2)
Cleanup 수행시간을 설정한다. 오후 11시 10분을 설정하고 싶다면 23:10으로 설정한다.<Age> (기본: 0, 단위: 일)
0보다 큰 경우, 일정 기간동안 한번도 접근되지 않은 콘텐츠를 삭제한다. 디스크를 미리 확보하여 서비스 시간 중 디스크 부족이 발생할 확률을 줄이기 위함이다.
<Listen>
모든 가상호스트가 Listen할 IP목록을 지정한다. 모든 가상호스트의 기본 Listen설정인 *:80은 0.0.0.0:80을 의미한다. 지정된 IP만을 열고 싶은 경우 다음과 같이 명확하게 설정한다.
# server.xml - <Server> <Cache> <Listen>10.10.10.10</Listen> <Listen>10.10.10.11</Listen> <Listen>127.0.0.2</Listen> </Cache>
<ConfigHistory> (기본: 30일)
STON은 설정이 변경될 때마다 모든 설정을 백업한다. 압축 후 ./conf/ 에 하나의 파일로 저장된다. 파일명은 “날짜_시간_HASH.tgz”로 생성된다.
20130910_174843_D62CA26F16FE7C66F81D215D8C52266AB70AA5C8.tgz
모든 설정이 완전히 동일하다면 같은 HASH값을 가진다. 설정 복구 가 호출되도 새로운 설정으로 저장된다. 백업된 설정은 Cleanup시간을 기준으로 설정된 날만큼만 저장된다. 설정파일 저장의 날짜제한은 없다.
강제 Cleanup¶
API호출로 Cleanup한다. <Age>
를 파라미터로 입력할 수 있다.
http://127.0.0.1:10040/command/cleanup
http://127.0.0.1:10040/command/cleanup?age=10
<Age>
가 0이라면 디스크 공간이 부족하다고 판단될 때만 Cleanup을 수행한다.
<Age>
파라미터가 0보다 크다면 해당 “일”동안 한번도 접근되지 않은 콘텐츠를 삭제한다.
가상호스트 기본설정¶
관리자는 각각의 가상호스트를 독립적으로 설정할 수 있다.
하지만 가상호스트를 생성할 때마다 동일한 설정을 반복하는 것은 매우 소모적이다.
모든 가상호스트는 <VHostDefault>
을 상속받는다.
![]()
단일 상속이다.
www.example.com의 경우 별도로 덮어쓰기(Overriding)한 값이 없으므로 A=1, B=2가 된다. 반면 img.example.com은 B=3으로 덮어쓰기했으므로 A=1, B=3이 된다. 관리자들은 보통 같은 서비스특성을 가지는 서비스를 한 서버에 같이 구성한다. 그러므로 상속은 매우 효과적인 방법이다.
<VHostDefault>
는 기능별로 묶인 5개의 하위 태그를 가진다.
# server.xml - <Server>
<VHostDefault>
<Options> ... </Options>
<OriginOptions> ... </OriginOptions>
<Media> ... </Media>
<Stats> ... </Stats>
<Log> ... </Log>
</VHostDefault>
예를 들어 17장. 미디어 기능은 <Media>
하위에 구성하는 식이다.
vhosts.xml 가상호스트 설정¶
실행파일과 같은 경로에 존재하는 vhosts.xml파일을 가상호스트 설정파일로 인식한다. 가상호스트 개수에 제한은 없다.
# vhosts.xml
<Vhosts>
<Vhost Status="Active" Name="www.example.com"> ... </Vhost>
<Vhost Status="Active" Name="img.example.com"> ... </Vhost>
<Vhost Status="Active" Name="vod.example.com"> ... </Vhost>
</Vhosts>
생성/파괴¶
<Vhosts>
하위에 <Vhost>
로 가상호스트를 설정한다.
# vhosts.xml - <Vhosts>
<Vhost Status="Active" Name="www.example.com">
<Origin>
<Address>10.10.10.10</Address>
</Origin>
</Vhost>
<Vhost>
가상호스트를 설정한다.Status (기본: Active)
Inactive인 경우 해당 가상호스트를 서비스하지 않는다. 캐싱된 콘텐츠는 유지된다.Name
가상호스트 이름. 중복될 수 없다.
<Vhost>
를 삭제하면 해당 가상호스트가 삭제된다.
삭제된 가상호스트의 모든 콘텐츠는 삭제대상이 된다.
다시 추가해도 콘텐츠는 되살아나지 않는다.
찾기¶
다음은 가장 간단한 형태의 HTTP요청이다.
GET / HTTP/1.1
Host: www.example.com
일반적인 Web서버는 Host헤더로 가상호스트를 찾는다.
하나의 가상호스트를 여러 이름으로 서비스하고 싶다면 <Alias>
를 사용한다.
# vhosts.xml - <Vhosts>
<Vhost Name="example.com">
<Alias>another.com</Alias>
<Alias>*.sub.example.com</Alias>
</Vhost>
<Alias>
가상호스트의 별명을 설정한다. 개수는 제한이 없다. 명확한 표현(another.com)과 패턴표현(*.sub.example.com)을 지원한다. 패턴은 복잡한 정규표현식이 아닌 prefix에 * 표현을 하나만 붙일 수 있는 간단한 형식만을 지원한다.
가상호스트 검색 순서는 다음과 같다.
<Vhost>
의Name
과 일치하는가?- 명시적인
<Alias>
와 일치하는가? - 패턴
<Alias>
를 만족하는가?
Default 가상호스트¶
요청을 처리할 가상호스트를 찾지못한 경우 선택될 가상호스트를 지정할 수 있다. 요청을 처리하고 싶지 않다면 설정하지 않아도 된다.
# vhosts.xml
<Vhosts>
<Vhost Status="Active" Name="www.example.com"> ... </Vhost>
<Vhost Status="Active" Name="img.example.com"> ... </Vhost>
<Default>www.example.com</Default>
</Vhosts>
<Default>
기본 가상호스트 이름을 설정한다. 반드시
<Vhost>
의Name
속성과 똑같은 문자열로 설정해야 한다.
서비스주소¶
서비스 주소를 설정한다.
# vhosts.xml - <Vhosts>
<Vhost Name="www.example.com">
<Listen>*:80</Listen>
</Vhost>
<Listen> (기본: *:80)
{IP}:{Port} 형식으로 서비스 주소를 설정한다. *:80 표현은 모든 NIC로부터의 80포트로 오는 요청을 처리한다는 의미다. 예를 들어 특정 IP(1.1.1.1)의 90포트로 서비스하고 싶다면 다음과 같이 설정한다.
# vhosts.xml - <Vhosts> <Vhost Name="www.example.com"> <Listen>1.1.1.1:90</Listen> </Vhost>
가상호스트-예외조건 (.txt)¶
서비스 중 다음과 같이 예외적인 상황이 필요할 때가 있다.
- 모든 POST요청은 허용하지 않지만, 특정 URL에 대한 POST요청은 허가한다.
- 모든 GET요청은 STON이 응답하지만, 특정 IP대역에 대해서는 원본서버로 바이패스한다.
- 특정 국가에 대해서는 전송속도를 제한한다.
이와같은 예외조건은 XML에 설정하지 않는다. 모든 가상호스트는 독립적인 예외조건을 가진다. 예외조건은 ./svc/가상호스트/ 디렉토리 하위에 TXT로 존재한다. 관련 기능에 대해 설명할 때 예외조건도 함께 다룬다.
가상호스트 목록확인¶
가상호스트 목록을 조회한다.
http://127.0.0.1:10040/monitoring/vhostslist
결과는 JSON형식으로 제공된다.
{
"version": "1.1.9",
"method": "vhostslist",
"status": "OK",
"result": [ "www.example.com","www.foobar.com", "site1.com" ]
}
설정 확인¶
서비스 중인 설정파일을 확인한다. txt파일들은 가상호스트(vhost)를 명확하게 지정해주어야 한다.
http://127.0.0.1:10040/conf/server.xml
http://127.0.0.1:10040/conf/vhosts.xml
http://127.0.0.1:10040/conf/querystring.txt?vhost=www.example.com
http://127.0.0.1:10040/conf/bypass.txt?vhost=www.example.com
http://127.0.0.1:10040/conf/ttl.txt?vhost=www.example.com
http://127.0.0.1:10040/conf/expires.txt?vhost=www.example.com
http://127.0.0.1:10040/conf/acl.txt?vhost=www.example.com
http://127.0.0.1:10040/conf/headers.txt?vhost=www.example.com
http://127.0.0.1:10040/conf/throttling.txt?vhost=www.example.com
http://127.0.0.1:10040/conf/postbody.txt?vhost=www.example.com
설정 목록¶
백업된 설정목록을 열람한다.
http://127.0.0.1:10040/conf/latest
http://127.0.0.1:10040/conf/history
결과는 JSON 형식으로 제공된다. 빠르게 마지막 설정상태만 확인하고 싶은 경우는 /conf/latest를 사용할 것을 권장한다.
{
"history" :
[
{
"id" : "5",
"conf-date" : "2013-11-06",
"conf-time" : "15:26:37",
"type" : "loaded",
"size" : "16368",
"hash" : "D62CA26F16FE7C66F81D215D8C52266AB70AA5C8",
"ver": "1.2.8"
},
{
"id" : "6",
"conf-date" : "2013-11-07",
"conf-time" : "07:02:21",
"type" : "modified",
"size" : "27544",
"hash" : "F81D215D8C52266AB70AA5C8D62CA26F16FE7C66",
"ver": "1.2.8"
}
]
}
id
설정의 고유 아이디 (Reload할때마다 +1)conf-date
설정 변경날짜conf-time
설정 변경시간type
설정이 반영된 형태 -loaded
STON이 시작될 때 -modified
설정이 (관리자 또는 WM에 의해) 변경될 때 -uploaded
설정파일 API를 통해 업로드 되었을 때 -restored
설정파일이 API를 통해 복구되었을 때size
설정파일 크기hash
설정파일을 SHA-1으로 hash한 값
설정 복구¶
hash값 또는 id를 기준으로 원하는 시점의 설정으로 되돌린다. hash와 id가 모두 명시된 경우 hash값이 우선한다. 정상적으로 Rollback된 경우 200 OK, 실패한 경우 500 Internal Error로 응답한다.
http://127.0.0.1:10040/conf/restore?hash=...
http://127.0.0.1:10040/conf/restore?id=...
설정 다운로드¶
hash값 또는 id를 기준으로 원하는 시점의 설정을 다운로드 한다. Content-Type은 “application/x-compressed”로 명시된다. hash와 id가 모두 명시된 경우 hash값이 우선하며, 해당 시점의 설정이 존재하지 않는 경우 404 NOT FOUND로 응답한다.
http://127.0.0.1:10040/conf/download?hash=...
http://127.0.0.1:10040/conf/download?id=...
설정 업로드¶
설정파일을 HTTP Post방식(Multipart 지원)으로 업로드 한다.
http://127.0.0.1:10040/conf/upload
다음과 같이 주소, Content-Length, Content-Type(=”multipart/form-data”)이 명확하게 선언되어 있어야 한다.
POST /conf/upload
Content-Length: 16455
Content-Type: multipart/form-data; boundary=......
업로드가 완료되면 압축을 해지한 뒤 즉시 반영시킨다.
Multipart방식에서는 “confile”을 기본 이름으로 사용한다.
이 값은 <Manager>
의 UploadMultipartName
속성에서 설정할 수 있다.
<form enctype="multipart/form-data" action="http://127.0.0.1:10040/conf/upload" method="POST">
<input name="confile" type="file" />
<input type="submit" value="Upload" />
</form>
2부. HTTP 서비스¶
4장. Caching 정책¶
이 장에서는 서비스의 핵심이 되는 TTL(Time To Live)과 Caching-Key 그리고 만료정책에 대해 설명한다. 저장된 콘텐츠는 TTL동안 유효하다. HTTP 규격은 TTL을 설정할 수 있도록 Cache-Control을 명시하고 있다. 하지만 이는 절대적인 것은 아니다. 다양한 방식의 TTL 정책과 5장. Caching 무효화 를 통해 서비스 품질을 높일 수 있다.
HTTP에는 콘텐츠를 구분하는 다양한 규격이 존재한다. 그만큼 Caching-Key도 다양하게 존재할 수 있다. 콘텐츠 변경이 없을수록 원본부하를 줄일 수 있을뿐만 아니라 쉽게 확장할 수 있다. 서비스에 최적화된 만료정책을 수립하는 다양한 방식에 대해 설명한다.
앞으로 설명되는 설정을 모든 가상호스트의 기본 설정으로 적용하고 싶다면 <VHostDefault>
하위에 설정한다.
반대로 특정 가상호스트에만 적용하고 싶다면 <Vhost>태그 하위에 설정한다.
**Caching-Key**란 콘텐츠를 구분하는 고유 값이다. 파일시스템에서 파일들과 구분되는 고유경로(예. /usr/conf.txt)를 가지는 것과 같은 개념이다. 흔히 Caching-Key는 URL과 혼동되기 쉽다. HTTP의 여러 기능에 따라 같은 URL이라고 하더라도 콘텐츠가 달라질 수 있다.
TTL (Time To Live)¶
TTL이란 저장된 콘텐츠의 유효시간이다. TTL을 길게 설정하면 원본서버의 부하는 줄어들지만 변경사항이 늦게 반영된다. 반대로 짧게 설정하면 너무 잦은 변경확인 요청으로 원본서버 부하가 높아진다. 운영의 묘미는 TTL을 적절히 설정하여 원본부하를 줄이는 것에 있다. TTL은 한번 설정되면 만료되기 전까지 바뀌지 않는다. 새로운 TTL은 파일이 만료되었을 때 적용된다. 관리자는 Purge , Expire , ExpireAfter , HardPurge 등의 API를 사용해 TTL을 변경할 수 있다.
기본 TTL¶
기본적으로 TTL은 원본서버의 응답에 따라 결정된다. TTL이 만료되기 전까지 저장된 콘텐츠로 서비스 된다. TTL이 만료되면 원본서버로 콘텐츠 변경여부( If-Modified-Since 또는 If-None-Match )를 확인한다. 원본서버가 304 Not Modified 응답을 준다면 TTL은 연장된다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<TTL>
<Res2xx Ratio="20" Max="86400">1800</Res2xx>
<NoCache Ratio="0" Max="5" MaxAge="0">5</NoCache>
<Res3xx>300</Res3xx>
<Res4xx>30</Res4xx>
<Res5xx>30</Res5xx>
<ConnectTimeout>3</ConnectTimeout>
<ReceiveTimeout>3</ReceiveTimeout>
<OriginBusy>3</OriginBusy>
</TTL>
Ratio
(0~100)를 제외한 모든 설정 단위는 초(sec) 다.
<Res2xx> (기본: 1800초, Ratio: 20, Max=86400)
원본서버가 200 OK로 응답했을 때 TTL을 설정한다. 콘텐츠를 처음 저장할 때<Res2xx>
초 뒤에 콘텐츠가 만료(TTL)되도록 설정한다. (TTL만료 후) 원본서버에서 변경되지 않았다면(304 Not Modified)Ratio
비율(0~100)만큼 TTL을 연장한다. TTL은 최대Max
까지 증가한다.<NoCache> (기본: 5초, Ratio: 0, Max=5, MaxAge=0)
<Res2xx>
와 동일하나 원본서버가 no-cache로 응답하는 경우에만 적용된다.cache-control: no-cache 또는 private 또는 must-revalidate
MaxAge
가 0보다 크다면 max-age를 줄 수 있다.Max-Age만큼 클라이언트에 Caching된다.
<Res3xx> (기본: 300초)
원본서버가 3xx로 응답했을 때 TTL을 설정한다. Redirect용도로 사용되는 경우가 많다.<Res4xx> (기본: 30초)
원본서버가 4xx로 응답했을 때 TTL을 설정한다. 404 Not Found 인 경우가 많다.<Res5xx> (기본: 30초)
원본서버가 5xx로 응답했을 때 TTL을 설정한다. 원본서버 내부 장애상황인 경우가 많다.<ConnectTimeout> (기본: 3초)
원본서버로 접속하지 못하는 경우 TTL을 설정한다. 콘텐츠가 이미 저장되어 있다면<ConnectTimeout>
초 만큼 TTL을 연장한다. 콘텐츠가 저장되어 있지 않다면<ConnectTimeout>
초 만큼 장애상황으로 응답한다. 이는 장애상황을 서비스한다는 의미보다는 TTL시간동안 (아마도 장애상황일) 원본서버에 부담을 주지 않기 위함이다.<ReceiveTimeout> (기본: 3초)
접속은 됐으나 데이터를 수신하지 못하는 경우 TTL을 설정한다.<ConnectTimeout>
과 의미적 동일하다.<OriginBusy> (기본: 3초)
과부하 판단 조건을 만족하면 원본서버 요청없이 만료된 콘텐츠의 TTL을 설정된 시간만큼 연장한다. 이는 원본서버의 부하를 가중시키지 않기 위함이다.
주석
TTL 값을 0으로 설정하면 서비스 직후 곧바로 만료된다. 만약 모든 요청에 대해 원본서버의 응답을 주고 싶다면 바이패스할 것을 권장한다.
Custom TTL¶
URL마다 별도로 TTL을 설정한다. 명확한 URL 또는 패턴 URL에 매칭되는 콘텐츠마다 고정된 TTL을 설정할 수 있다. /svc/{가상호스트 이름}/ttl.txt 에 설정한다.
# /svc/www.example.com/ttl.txt
# 구분자는 콤마(,)이며 시간 단위는 초이다.
*.jsp, 10
/,5
/index.html, 5
/script/*.js, 300
/image/ad.jpg, 1800
모든 페이지(html, php, jsp 등)에 별도의 TTL을 설정하기 위하여 *.html을 추가하였더라도 첫 페이지(/)에는 설정되지 않는다. 원본서버가 첫 페이지를 어떤 페이지(예를 들어 index.php로 default.jsp 등)로 설정하였는지 HTTP 프로토콜로는 알 수 없다. 그러므로 모든 페이지에 별도의 TTL을 설정하려면 반드시 /를 추가해야 한다.
TTL 우선순위¶
적용할 TTL설정의 우선순위를 설정한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<TTL Priority="cc_nocache, custom, cc_maxage, rescode">
... (생략) ...
</TTL>
<TTL>
의 Priority (기본: cc_nocache, custom, cc_maxage, rescode)
속성으로 설정한다.
cc_nocache
원본이 Cache-Control: no-cache로 응답한 경우custom
caching-policy-customttlcc_maxage
원본이 Cache-Control에 maxage를 명시한 경우rescode
원본 응답코드별 기본 TTL
비정상 TTL 연장¶
원본서버 종료로 인해 응답이 오지 않는 경우에는 장애판단이 명확하지만 간혹 정상적으로 응답하면서 장애상황인 경우가 발생한다. 예를 들어 콘텐츠를 저장하는 Storage와의 연결을 잃거나, 뭔가 정상처리가 불가능하다고 판단하는 경우가 있을 수 있다. 전자의 경우 4xx응답(주로 404 Not Found ), 후자는 5xx응답(주로 500 Internal Error )을 받게된다.
하지만 이미 관련 콘텐츠가 저장되어 있다면, 원본의 응답을 믿는 것보다 TTL을 연장시켜 서비스 전체장애가 발생하지 않도록 하는편이 효과적이다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<TTLExtensionBy4xx>OFF</TTLExtensionBy4xx>
<TTLExtensionBy5xx>ON</TTLExtensionBy5xx>
<TTLExtensionBy4xx>
OFF (기본)
4xx 응답으로 콘텐츠를 갱신한다.ON
304 not modified를 받은 것처럼 동작한다.
의도된 4xx응답이 아닌지 주의해야 한다.
<TTLExtensionBy5xx>
ON (기본)
304 Not Modified 를 받은 것처럼 동작한다.OFF
5xx 응답으로 콘텐츠를 갱신한다.
정상적인 서버라면 5xx로 응답하지 않는다. 주로 서버의 일시적인 장애로부터 콘텐츠를 무효화하여 원본부하를 가중시키지 않기 위한 용도로 사용된다.
갱신정책¶
TTL이 만료된 콘텐츠의 경우 원본서버에서 갱신여부를 확인한 뒤 서비스가 이루어진다.
![]()
변경확인 후 응답
- TTL이 유효하다. 즉시 응답한다.
- TTL이 만료되어 원본서버로 변경확인(If-Modified-Since)을 요청한다. 변경확인이 될때까지 클라이언트에게 응답하지 않는다.
- 원본서버에서 응답이 오면 TTL을 연장하거나 콘텐츠를 변경(Swap)한다. 원본서버에서 확인이 되었으므로 클라이언트에게 응답한다.
- 변경확인이 된 콘텐츠이므로 다음 TTL 만료시까지 즉시 응답한다.
고화질 동영상이나 게임처럼 상대적으로 반응성보다 전송속도가 중요한 서비스에서는 이런 방식이 큰 문제가 되지 않는다. 대용량 데이터의 경우 원본서버가 10초만에 갱신에 대한 응답을 한다고 하더라도 전송에 몇 분씩 소요되기 때문에 상대적으로 원본의 반응성이 크게 중요하지 않다. 오히려 접근 빈도가 높지 않은 콘텐츠이기 때문에 반드시 갱신확인이 이루어져야 한다.
하지만 쇼핑몰과 같은 경우 상황은 다르다. 웹 페이지는 빠르게 로딩되는 것이 무엇보다 중요하다. 1~2초 안에 클라이언트 화면구성이 모두 끝나야 한다. 전송속도보다 반응속도가 더 중요하다는 말이다.
이때 TTL이 만료되어 원본서버에게 갱신확인을 해야 한다면 매우 큰 지연이 발생할 수 있다. 보통의 쇼핑몰이 수백만개의 콘텐츠를 동시에 서비스 하는 것을 감안할 때 항상 원본서버로부터 갱신확인 작업이 발생하고 있다고 생각해야 한다. 자칫 원본서버 장애가 발생하거나 네트워크 장애가 발생한다면 최악이다.
우리가 원하는 것은 어떠한 원본서버의 장애나 지연으로부터 캐싱된 콘텐츠가 안전하게 전송되는 것이다.
![]()
장애가 두렵지 않다!
이런 차이점 때문에 백그라운드 콘텐츠 갱신기능이 개발되었다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<RefreshExpired>ON</RefreshExpired>
<RefreshExpired>
ON (기본)
변경확인 후 응답한다.OFF
변경확인 응답을 기다리지 않고 응답한다. 새로운 콘텐츠의 다운로드가 완료되면 그때 변경(Swap)한다.
OFF
설정의 더 큰 이유는 콘텐츠가 대부분 자주 바뀌지 않기 때문이다.
![]()
변경에 민감하지 않다면 기다리지 않는다.
위 그림에서 원본서버와의 갱신작업이 모두 백그라운드로 이루어지기 때문에 캐싱된 콘텐츠는 기다림없이 즉시 클라이언트에게 서비스된다. 원본서버가 304 Not Modified 로 응답한다면 TTL만 연장된다. 파일이 갱신되어 원본서버에서 200 OK를 응답한 경우 해당 파일이 완전히 다운로드된 후에 파일이 부드럽게 교체된다. 콘텐츠가 바뀌어도 이전 콘텐츠(초록색)를 다운로드 받던 사용자들은 정상적으로 다운로드가 진행된다. 파일 교체 이후 접근된 사용자들(겨자색)은 바뀐 파일로 서비스 된다. 콘텐츠 갱신, 네트워크 장애, 원본서버 장애 등 어떠한 변수에도 콘텐츠 갱신은 백그라운드로 진행되기 때문에 실제 서비스에는 전혀 지연이 없다.
클라이언트 no-cache 요청시 TTL만료¶
클라이언트 HTTP요청에 no-cache 설정이 하나 이상 명시된 경우 해당 콘텐츠를 즉시 만료시킬 수 있다.
GET /logo.jpg HTTP/1.1
...
cache-control: no-cache 또는 cache-control:max-age=0
pragma: no-cache
...
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<NoCacheRequestExpire>OFF</NoCacheRequestExpire>
<NoCacheRequestExpire>
OFF (기본)
무시한다.ON
TTL을 즉시 만료한다.
만료된 콘텐츠는 갱신정책 에 따른다.
Accept-Encoding 헤더¶
같은 URL에 대한 HTTP요청이라도 Accept-Encoding헤더의 존재 유무에 따라 다른 콘텐츠가 캐싱될 수 있다. 원본서버에 요청을 보내는 시점에 압축여부를 알 수 없다. 응답을 받았다고해도 압축여부를 매번 비교할 수도 없다.
![]()
원본서버가 어떤 응답을 줄지 알 수 없다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<AcceptEncoding>ON</AcceptEncoding>
<AcceptEncoding>
ON (기본)
HTTP 클라이언트가 보내는 Accept-Encoding 헤더를 인식한다.OFF
HTTP 클라이언트가 보내는 Accept-Encoding 헤더를 무시한다.
원본서버에서 압축을 지원하지 않거나, 압축이 필요없는 대용량 파일의 경우 OFF
로 설정하는 것이 바람직하다.
대소문자 구분¶
원본서버의 대소문자 구분여부를 능동적으로 알 수 없다.
![]()
아마도 같은 콘텐츠이거나 404가 발생한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<CaseSensitive>ON</CaseSensitive>
<CaseSensitive>
ON (기본)
URL 대소문자를 구문한다.OFF
URL 대소문자를 구분하지 않는다. 모두 소문자로 처리된다.
QueryString 구분¶
QueryString에 의하여 동적으로 생성되는 콘텐츠가 아니라면 QueryString을 인식하는 것은 불필요하다. 아무 의미없는 Random값이나 항상 변하는 시간 값이 매번 붙는다면 원본에 엄청난 부하가 발생할 수 있다.
![]()
동적 콘텐츠가 아니라면 같은 콘텐츠일 가능성이 높다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<ApplyQueryString Collective="OFF">ON</ApplyQueryString>
<ApplyQueryString>
ON (기본)
QueryString을 인식한다. 예외조건에 만족하면 QueryString이 무시된다.OFF
QueryString을 무시한다. 예외조건에 만족하면 QueryString을 인식한다.
QueryString-예외조건은 /svc/{가상호스트 이름}/querystring.txt에 설정한다.
# ./svc/www.example.com/querystring.txt
/private/personal.jsp?login=ok*
/image/ad.jpg
예외조건이 <ApplyQueryString>
설정에 따라 의미가 달라짐에 주의한다.
명확한 URL또는 패턴(*만 허용한다)으로 설정이 가능하다.
Collective
속성은 5장. Caching 무효화 API가 호출되었을 때 대상을 지정한다.
Collective
OFF (기본)
파라미터 URL만을 대상으로 지정한다.ON
파라미터 URL뿐만 아니라 URL에 QueryString이 존재하는 모든 컨텐츠를 대상으로 지정한다.
Collective
속성이 ON이고 파일이 많을수록 5장. Caching 무효화 에 CPU부하가 높아진다.
관련 파일을 검색하는 소요시간이 길어질 수 있어 예기치 않은 문제를 일으킬 수 있다.
가급적 QueryString까지 붙은 명확한 URL로 5장. Caching 무효화 API를 호출할 것을 권장한다.
Vary 헤더¶
Vary헤더를 인식하여 콘텐츠를 구분한다. 일반적으로 Vary헤더는 Cache서버의 성능을 급격히 떨어트리는 원흉이다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<VaryHeader />
<VaryHeader>
원본서버가 응답한 Vary헤더 중 지원할 헤더목록을 설정한다. 구분자는 콤마(,)를 사용한다.
예를 들어 원본서버가 다음과 같이 Vary헤더를 보냈다고 하더라도 <VaryHeader>
가 설정되어 있지 않다면 무시한다.
Vary: Accept-Encoding, Accept, User-Agent
User-Agent를 제외한 Accept-Encoding과 Accept헤더만을 인식하도록 하려면 다음과 같이 설정한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<VaryHeader>Accept-Encoding, Accept</VaryHeader>
원본서버가 보낸 모든 Vary헤더를 인식하게 하려면 다음과 같이 설정한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<VaryHeader>*</VaryHeader>
POST 요청 캐싱¶
POST 요청을 Caching하도록 설정한다. POST 요청의 특성상 URL은 같지만 Body데이터가 다를 수 있다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<PostRequest MaxContentLength="102400" BodySensitive="ON">OFF</PostRequest>
<PostRequest>
OFF (기본)
POST요청이 오면 세션을 종료한다.ON
POST요청을 Caching한다.
실제로 POST요청을 처리하는 대부분의 경우는 Body데이터를 Caching-Key로 사용한다.
BodySensitive
속성과 예외조건을 통해 정교한 설정이 가능하다.
BodySensitive
ON (기본)
Body데이터까지 Caching-Key로 인식한다. 최대 길이는MaxContentLength (기본: 102400 Bytes)
속성으로 제한한다. 예외조건에 만족하면 Body데이터를 무시한다.OFF
Body데이터는 무시한다. 예외조건에 만족하면 Body데이터를 인식한다.
POST요청 예외조건은 /svc/{가상호스트 이름}/postbody.txt에 설정한다.
# /svc/www.example.com/postbody.txt
/bigsale/*.php?nocache=*
/goods/search.php
예외조건이 BodySensitive
설정에 따라 의미가 달라짐에 주의한다.
명확한 URL 또는 패턴(*만 허용한다.)으로 설정이 가능하다.
이 설정은 GET/POST 바이패스 와 정책적으로 혼란스러울 수 있다.
<BypassPostRequest> (기본: ON)
에 의해 POST요청이 캐싱되지 않을 수 있다.
따라서 POST요청을 캐싱하기 위해서는 <BypassPostRequest>
를 OFF
또는 예외조건을 설정해야 한다.
정리하면 우선순위는 다음과 같다.
- 바이패스 조건( GET/POST 바이패스 )에 만족할 경우 원본서버로 바이패스 한다.
- Content-Length헤더가 없다면 연결을 종료한다.
PostRequest
가ON
으로 설정되어 있고 Content-Length가MaxContentLength
속성 값을 넘지 않는다면 캐싱모듈에 의해 처리된다.- 이상의 시나리오에서 처리되지 않은 요청은 종료한다.
주석
MaxContentLength
속성을 너무 크게 설정할 경우 Caching-Key 관리에 많은 메모리가 필요하다.
가능한 작게 설정하는 것이 좋다.
5장. Caching 무효화¶
이 장에서는 Caching된 콘텐츠를 무효화하는 방법에 대해 설명한다. 업계용어로 Purge로 통칭하지만 다양한 상황과 환경으로 인해 세분화된 API가 필요하다.
원본으로부터 캐싱된 콘텐츠는 TTL (Time To Live) 에 기반한 갱신주기를 가진다. 하지만 명백히 콘텐츠가 변경되었고 관리자가 이를 즉시 반영하고 싶을 경우 TTL (Time To Live) 이 만료될 때까지 기다릴 필요는 없다. Purge / Expire / HardPurge 등을 사용하면 즉시 콘텐츠를 무효화시킬 수 있다.
무효화 API는 단순히 브라우저에 의해 호출되는 경우도 있지만 자동화되어 있는 경우가 많다. 가령 FTP를 통한 파일 업로드가 끝나면 즉시 Purge 를 호출하는 식이다. 관리자는 다음과 같이 몇가지 동작방식에 대해 설정할 수 있다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<Purge2Expire>NONE</Purge2Expire>
<RootPurgeExpire>ON</RootPurgeExpire>
<ResCodeNoCtrlTarget>200</ResCodeNoCtrlTarget>
<Purge2Expire> (기본: NONE)
Purge 요청을 설정에 따라 Expire 로 처리한다. 예를 들어 특정 패턴(*.jpg)를 Purge 하는 경우 의도하지 않게 많은 컨텐츠가 삭제되어 원본에 과도한 부하를 발생시킬 수 있다. 이런 경우 Expire 로 처리하도록 설정하면 과도한 원본부하를 방지할 수 있다.
<RootPurgeExpire> (기본: ON)
전체 콘텐츠에 대한 의도하지 않은 Purge / Expire 는 과도한 원본서버 부하를 발생시킬 수 있다. 이 설정을 통하여 전체 콘텐츠에 대한 Purge / Expire 를 차단할 수 있다. 이 설정은
<Purge2Expire>
보다 우선한다.<ResCodeNoCtrlTarget> (기본: 200)
Purge , Expire , HardPurge , ExpireAfter 의 대상객체가 없을 때의 HTTP 응답코드를 설정한다.
대상 지정은 URL, 패턴 2가지로 표현한다.
example.com/logo.jpg // URL
example.com/img/ // URL
example.com/img/*.jpg // 패턴
example.com/img/* // 패턴
명확한 URL 외에 패턴(*.jpg)으로 무효화가 가능하다. 하지만 작업을 수행하기 전까지 대상개수를 명확히 알 수 없다. 이는 자칫 관리자의 의도와 다르게 너무 많은 대상을 지정할 수 있다. 이는 실제로 CPU자원을 너무 많이 소모하게 되어 시스템 전체에 부담을 줄 수 있다.
그러므로 실 서비스 중에는 명확한 URL만을 사용할 것을 강력히 권장한다. 패턴표현은 서비스에서 배제된 상태에서 관리용도로 사용하기 위함이다.
주석
보안적인 이유로 example.com/files/ 같은 특정 디렉토리에 대한 접근은 403 FORBIDDEN등으로 차단된다. 하지만 루트 디렉토리는 예외를 가진다. 예를 들어 사용자가 example.com에 접근하면 브라우저는 루트 디렉토리(/)를 요청한다.
GET / HTTP/1.1
Host: example.com
이에 대해 웹서버는 관리자가 설정한 기본 페이지(아마도 index.html 또는 index.htm)로 응답한다. 분명 웹 서비스 구성에서 루트 디렉토리(/)는 디렉토리가 아닌 페이지로 동작한다.
하지만 Cache서버는 루트 디렉토리(/)에 접근했더니 200 OK 페이지가 왔다고 이해한다. 심지어 원본서버가 어떤 페이지를 응답했는지 알지 못한다. 간단히 정리하면 Cache서버의 관점에서는 디렉토리 표현도 URL의 한 종류일 뿐이다.
example.com/img/ // example.com 가상호스트의 /img/ 에 접근한 결과 페이지
example.com/ // example.com 가상호스트의 기본 페이지(/)
example.com/img/* // example.com 가상호스트의 /img 디렉토리와 그 하위 페이지
example.com/* // example.com 가상호스트의 모든 콘텐츠
Purge¶
타겟 컨텐츠를 무효화시켜 원본서버로부터 컨텐츠를 다시 다운로드 받도록 한다. Purge후 최초 접근 시점에 원본서버로부터 컨텐츠를 다시 캐싱한다. 만약 원본서버에 장애가 발생하여 컨텐츠를 가져올 수 없다면 무효화된 컨텐츠를 다시 복원시켜 서비스에 장애가 없도록 처리한다. 이렇게 복원된 컨텐츠는 해당 시점으로부터 ConnectTimeout설정만큼 뒤에 갱신한다.
http://127.0.0.1:10040/command/purge?url=...
타겟 컨텐츠는 URL, 패턴으로 지정할 수 있을 뿐만 아니라 “|”(Vertical Bar)를 구분자를 사용하여 복수의 도메인에 복수의 타겟을 지정할 수 있다. 만약 도메인 이름이 생략되었다면 최근 사용된 도메인을 사용한다.
http://127.0.0.1:10040/command/purge?url=http://www.site1.com/image.jpg
http://127.0.0.1:10040/command/purge?url=www.site1.com/image.jpg
http://127.0.0.1:10040/command/purge?url=www.site1.com/image/bmp/
http://127.0.0.1:10040/command/purge?url=www.site1.com/image/*.bmp
http://127.0.0.1:10040/command/purge?url=www.site1.com/image1.jpg|/css/style.css|/script.js
http://127.0.0.1:10040/command/purge?url=www.site1.com/image1.jpg|www.site2.com/page/*.html
결과는 JSON형식으로 제공된다. 타겟 컨텐츠 개수/용량 및 처리시간(단위: ms)이 명시된다. 이미 Purge 된 컨텐츠는 다시 Purge되지 않는다.
{
"version": "2.0.0",
"method": "purge",
"status": "OK",
"result": { "Count": 24, "Size": 3747491, "Time": 12 }
}
<Purge2Expire>
를 통해 특정조건의 Purge를 Expire로 동작하도록 설정할 수 있다.
결과없는 응답에 대해서는 <ResCodeNoCtrlTarget>
로 HTTP 응답코드를 설정할 수 있다.
주석
원본서버가 장애로 인해 모두 배제되었다면 컨텐츠를 갱신할 수 없기 때문에 Purge가 동작하지 않는다.
Expire¶
타겟 컨텐츠의 TTL을 즉시 만료시킨다. Expire후 최초 접근 시점에 원본서버로부터 변경여부를 확인한다. 변경되지 않았다면 TTL연장만 있을 뿐 컨텐츠 다운로드는 발생하지 않는다.
http://127.0.0.1:10040/command/expire?url=...
그 외의 모든 동작은 Purge 와 동일하다.
ExpireAfter¶
타겟 컨텐츠의 TTL만료 시간을 현재(API호출시점)로부터 입력된 시간(초)만큼 뒤에 설정한다. ExpireAfter로 만료시간을 앞당겨 컨텐츠를 더 빨리 갱신하거나, 반대로 만료시간을 늘려 원본서버 부하를 줄일 수 있다.
http://127.0.0.1:10040/command/expireafter?sec=86400&url=...
함수 호출규격은 Purge / Expire 와 유사하지만 sec파라미터(단위: 초)를 통해
TTL만료 시간을 지정할 수 있다.
sec가 생략된다면 기본 값은 1일(86400초)로 설정되며 0을 입력할 경우 실패한다.
결과는 Purge / Expire 와 동일하지만 원본서버 장애여부와 상관없이 동작한다.
결과없는 응답에 대해서는 <ResCodeNoCtrlTarget>
로 HTTP 응답코드를 설정할 수 있다.
주석
ExpireAfter는 캐싱되어있는 컨텐츠의 현재 만료시간만을 설정할 뿐 커스텀TTL이나 설정된 기본 TTL을 변경시키는 API가 아니다. ExpireAfter 호출뒤에 캐싱된 컨텐츠들은 영향을 받지 않는다.
url파라미터를 먼저 입력하는 경우 sec파라미터가 url파라미터의 QueryString으로 인식될 수 있다. 그러므로 sec파라미터가 먼저 입력되는 것이 안전하다.
HardPurge¶
Purge / Expire / ExpireAfter 이상의 API는 원본서버 장애상황에서도 컨텐츠가
사라지지 않고 정상적으로 동작한다.
하지만 HardPurge는 컨텐츠의 완전한 삭제를 의미한다.
HardPurge는 가장 강력한 삭제방법이지만 삭제한 컨텐츠는 원본서버에 장애가 발생해도 되살릴 수 없다.
결과없는 응답에 대해서는 <ResCodeNoCtrlTarget>
로 HTTP 응답코드를 설정할 수 있다.
http://127.0.0.1:10040/command/hardpurge?url=...
HTTP Method¶
무효화 API를 확장 HTTP Method로 호출할 수 있다.
PURGE /sample.dat HTTP/1.1
host: ston.winesoft.co.kr
HTTP Method는 기본적으로 Manager포트와 서비스(80)포트에서 동작한다. 서비스포트로 요청되는 HTTP Method의 관리자 설정 에서 설정한다.
POST 규격¶
무효화 API를 다음과 같이 POST로 호출할 수 있다.
POST /command/purge HTTP/1.1
Content-Length: 37
url=http://ston.winesoft.co.kr/sample.dat
6장. HTTP 요청/응답¶
이 장에서는 HTTP 클라이언트 세션과 요청을 처리하는 방식에 대해 설명한다. 서비스의 핵심기능으로 보기엔 어려운 내용들이 많으니 머리아파하지 않아도 된다. 일부 HTTP에 대한 이해가 없다면 어려울 수 있는 부분이 있는데 이럴 때는 기본설정을 사용하길 바란다. 전체적으로 기본 설정을 그대로 사용해도 서비스에는 전혀 지장이 없는 내용들이다.
세션관리¶
HTTP 클라이언트가 서버(STON)에 접속하면 HTTP 세션이 생성된다. 클라이언트는 HTTP 세션을 통해 서버에 저장된 여러 콘텐츠를 서비스 받는다. 요청부터 응답까지를 하나의 HTTP 트랜잭션 이라고 부른다. HTTP 세션은 여러 HTTP 트랜잭션을 순차적으로 처리한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<ConnectionHeader>keep-alive</ConnectionHeader>
<ClientKeepAliveSec>10</ClientKeepAliveSec>
<KeepAliveHeader Max="0">ON</KeepAliveHeader>
<ConnectionHeader> (기본: keep-alive)
클라이언트에게 보내는 HTTP응답의 Connection헤더(keep-alive
또는close
)를 설정한다.<ClientKeepAliveSec> (기본: 10초)
클라이언트 세션과 아무런 통신이 없는 상태로 설정된 시간이 경과하면 세션을 종료한다. 시간을 너무 길게 설정하면 통신을 하지 않는 세션이 지나치게 많아진다. 너무 많은 세션을 유지하는 것만으로도 시스템엔 부하가 된다.<KeepAliveHeader>
ON (기본)
HTTP응답에 Keep-Alive헤더를 명시한다.Max (기본: 0)
를 0보다 크게 설정하면 Keep-Alive헤더의 값으로Max
값이 명시된다. 이후 HTTP 트랜잭션이 발생할때마다 1씩 차감된다.
OFF
HTTP응답에 Keep-Alive헤더를 생략한다.
HTTP 세션 유지정책¶
STON은 가급적 Apache의 정책을 따른다. 특히 세션유지 정책은 HTTP헤더 값에 따른 변수가 많다. HTTP 세션 유지정책에 영향을 주는 요소는 다음과 같다.
- 클라이언트 HTTP요청에 명시된 Connection헤더 (“Keep-Alive” 또는 “Close”)
- 가상호스트
<Connection>
설정 - 가상호스트 세션 Keep-Alive시간 설정
- 가상호스트
<Keep-Alive>
설정
클라이언트 HTTP요청에 “Connection: Close”로 명시되어 있는 경우
GET / HTTP/1.1 ...(생략)... Connection: Close
이같은 HTTP요청에 대해서는 가상호스트 설정여부와 상관없이 “Connection: Close”로 응답한다. Keep-Alive헤더는 명시되지 않습니다.
HTTP/1.1 200 OK ...(생략)... Connection: Close
이 HTTP 트랜잭션이 완료되면 HTTP 연결을 종료한다.
<ConnectionHeader>
가Close
로 설정된 경우# server.xml - <Server><VHostDefault><Options> # vhosts.xml - <Vhosts><Vhost><Options> <ConnectionHeader>Close</ConnectionHeader>
클라이언트 HTTP요청과 상관없이 “Connection: Close”로 응답한다. Keep-Alive헤더는 명시되지 않는다.
HTTP/1.1 200 OK ...(생략)... Connection: Close
<KeepAliveHeader>
가OFF
로 설정된 경우# server.xml - <Server><VHostDefault><Options> # vhosts.xml - <Vhosts><Vhost><Options> <ConnectionHeader>Keep-Alive</ConnectionHeader> <KeepAliveHeader>OFF</KeepAliveHeader>
Keep-Alive헤더가 명시되지 않는다. HTTP 세션은 지속적으로 재사용가능하다.
HTTP/1.1 200 OK ...(생략)... Connection: Keep-Alive
<KeepAliveHeader>
가ON
으로 설정된 경우# server.xml - <Server><VHostDefault><Options> # vhosts.xml - <Vhosts><Vhost><Options> <ConnectionHeader>Keep-Alive</ConnectionHeader> <ClientKeepAliveSec>10</ClientKeepAliveSec> <KeepAliveHeader>ON</KeepAliveHeader>
Keep-Alive헤더가 명시된다. timeout값은 세션 Keep-Alive시간 설정을 사용한다.
HTTP/1.1 200 OK ...(생략)... Connection: Keep-Alive Keep-Alive: timeout=10
주석
<
<Keep-Alive>
와<ClientKeepAliveSec>
의 관계 ><Keep-Alive>
설정시<ClientKeepAliveSec>
를 참고하지만<ClientKeepAliveSec>
는 보다 근본적인 문제와 관련이 있다. 성능이나 자원적으로 가장 중요한 이슈는 Idle세션(=HTTP 트랜잭션이 발생되지 않는 세션)의 정리시점을 잡는 것이다. HTTP 헤더 설정은 동적으로 변경되거나 때로 생략될 수 있지만 Idle세션 정리는 훨씬 민감한 문제이다. 이런 이유 때문에<ClientKeepAliveSec>
는<KeepAliveHeader>
에 통합되지 않고 별도로 존재한다.<KeepAliveHeader>
의Max
속성이 설정된 경우# server.xml - <Server><VHostDefault><Options> # vhosts.xml - <Vhosts><Vhost><Options> <ConnectionHeader>Keep-Alive</ConnectionHeader> <ClientKeepAliveSec>10</ClientKeepAliveSec> <KeepAliveHeader Max="50">ON</KeepAliveHeader>
Keep-Alive헤더에 max값을 명시한다. 이 세션은 max회만큼 사용이 가능하며 HTTP 트랜잭션이 진행될때마다 1씩 감소된다.
HTTP/1.1 200 OK ...(생략)... Connection: Keep-Alive Keep-Alive: timeout=10, max=50
Keep-Alive의 max가 만료된 경우
위의 설정대로 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
클라이언트 Cache-Control¶
클라이언트 Cache-Control과 관련된 설정을 다룬다.
Age 헤더¶
Age헤더는 캐싱된 순간부터 경과시간(초)을 의미하며 RFC2616 - 13.2.3 Age Calculations 에 의하여 계산된다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<AgeHeader>OFF</AgeHeader>
<AgeHeader>
OFF (기본)
Age헤더를 생략한다.ON
Age헤더를 명시한다.
Expires 헤더¶
Expires헤더를 재설정한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<RefreshExpiresHeader Base="Access">OFF</RefreshExpiresHeader>
<RefreshExpiresHeader>
OFF (기본)
원본서버에서 응답한 Expires헤더를 클라이언트에게 명시한다. 원본서버에서 Expires헤더가 생략되었다면 클라이언트 응답에도 Expires헤더가 생략된다.ON
Expires조건을 반영하여 Expires헤더를 명시한다. 조건에 해당하지 않는 콘텐츠는OFF
설정과 동일하게 동작한다.
Expires조건은 Apache의 mod_expires 와 동일하게 동작한다. 특정 조건(URL이나 MIME Type)에 해당하는 콘텐츠의 Expires헤더와 Cache-Control 값을 설정할 수 있다. Cache-Control의 max-age값은 설정된 Expires시간에서 요청한 시간을 뺀 값이 된다.
Expires조건은 /svc/{가상호스트 이름}/expires.txt에 설정한다.
# /svc/www.exmaple.com/expires.txt
# 구분자는 콤마(,)이며 {조건},{시간},{기준} 순서로 표기한다.
$URL[/test.jpg], 86400
/test.jpg, 86400
*, 86400, access
/test/1.gif, 60 sec
/test/*.dat, 30 min, modification
$MIME[application/shockwave], 1 years
$MIME[application/octet-stream], 7 weeks, modification
$MIME[image/gif], 3600, modification
조건
URL과 MIME Type 2가지로 설정이 가능하다. URL일 경우 $URL[...]로, MIME Type일 경우 $MIME[...]로 표기한다. 패턴표현이 가능하며 $표현이 생략된 경우 URL로 인식한다.
시간
Expires만료시간을 설정한다. 시간단위 표현을 지원하며 단위를 명시하지 않을 경우 초로 계산된다.
기준
Expires만료시간의 기준시점을 설정한다. 별도로 기준시점을 명시하지 않으면 Access가 기준시점으로 명시된다. Access는 현재 시간을 기준으로 한다. 다음은 MIME Type이 image/gif인 파일에 대하여 접근시간으로부터 1일 12시간 후로 Expires헤더 값을 설정하는 예제이다.
$MIME[image/gif], 1 day 12 hours, access
Modification은 원본서버에서 보낸 Last-Modified를 기준으로 한다. 다음은 모든 jpg파일에 대하여 Last-Modified로부터 30분 뒤를 Expires값으로 설정하는 예제이다.
*.jpg, 30min, modification
Modification의 경우 계산된 Expires값이 현재시간보다 과거의 시간일 경우 현재시간을 명시한다. 만약 원본서버에서 Last-Modified헤더를 제공하지 않는다면 Expires헤더를 보내지 않는다.
ETag 헤더¶
클라이언트에게 보내는 HTTP응답에 ETag 헤더 명시여부를 설정한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<ETagHeader>ON</ETagHeader>
<ETagHeader>
ON (기본)
ETag헤더를 명시한다.OFF
ETag헤더를 생략한다.
기본응답 헤더¶
원본 비표준 헤더¶
성능과 보안상의 이유로 원본서버가 보내는 헤더 중 표준헤더만을 선택적으로 인식한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<OriginalHeader>OFF</OriginalHeader>
<OriginalHeader>
OFF (기본)
표준헤더가 아니라면 무시한다.ON
cookie, set-cookie, set-cookie2를 제외한 모든 헤더를 저장하여 클라이언트에게 전달한다. 단, 메모리와 저장비용을 좀 더 소비한다.
Via 헤더¶
클라이언트에게 보내는 HTTP응답에 Via 헤더 명시여부를 설정한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<ViaHeader>ON</ViaHeader>
<ViaHeader>
ON (기본)
Via헤더를 다음과 같이 명시한다.Via: STON/2.0.0
OFF
Via헤더를 생략한다.
Server 헤더¶
클라이언트에게 보내는 HTTP응답에 Server 헤더 명시여부를 설정한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<ServerHeader>ON</ServerHeader>
<ServerHeader>
ON (기본)
원본서버의 Server헤더를 명시한다.OFF
Server헤더를 생략한다.
클라이언트 요청/응답 헤더 변경¶
클라이언트 HTTP요청과 응답을 특정 조건에 따라 변경한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<ModifyHeader FirstOnly="OFF">OFF</ModifyHeader>
<ModifyHeader>
OFF (기본)
변경하지 않는다.ON
헤더 변경조건에 따라 헤더를 변경한다.
헤더 변경시점을 정확히 이해하자.
HTTP 요청헤더 변경시점
클라이언트 HTTP 요청을 최초로 인식하는 시점에 헤더를 변경한다. 헤더가 변경되었다면 변경된 상태로 Cache 모듈에서 처리된다. 단, Host헤더와 URI는 변경할 수 없다.
HTTP 응답헤더 변경시점
클라이언트 응답 직전에 헤더를 변경한다. 단, Content-Length는 변경할 수 없다.
헤더 변경조건은 /svc/{가상호스트 이름}/headers.txt에 설정한다. 헤더는 멀티로 설정이 가능하므로 조건과 일치한다면 모든 변경설정이 순차적으로 모두 적용된다.
최초 조건에만 변경을 원할 경우 FirstOnly
속성을 ON
으로 설정한다.
서로 다른 조건이 같은 헤더를 변경하는 경우 set
에 의해 Last-Win이 되거나 명시적으로 put
append
할 수 있다.
# /svc/www.example.com/headers.txt
# 구분자는 콤마(,)이다.
# 요청변경
# {Match}, {$REQ}, {Action(set|put|append|unset)} 순서로 표기한다.
$IP[192.168.1.1], $REQ[SOAPAction], unset
$IP[192.168.2.1-255], $REQ[accept-encoding: gzip], set
$IP[192.168.3.0/24], $REQ[cache-control: no-cache], append
$IP[192.168.4.0/255.255.255.0], $REQ[x-custom-header], unset
$IP[AP], $REQ[X-Forwarded-For], unset
$HEADER[user-agent: *IE6*], $REQ[accept-encoding], unset
$HEADER[via], $REQ[via], unset
$URL[/source/*.zip], $REQ[accept-encoding: deflate], set
# 응답변경
# {Match}, {$RES}, {Action(set|put|append|unset)}, {condition} 순서로 표기한다.
# {condition}은 특정 응답코드에 한하여 헤더를 변경할 수 있지만 필수는 아니다.
$IP[192.168.1.1], $RES[via: STON for CDN], set
$IP[192.168.2.1-255], $RES[X-Cache], unset, 200
$IP[192.168.3.0/24], $RES[cache-control: no-cache, private], append, 3xx
$IP[192.168.4.0/255.255.255.0], $RES[x-custom-header], unset
$HEADER[user-agent: *IE6*], $RES[vary], unset
$HEADER[x-custom-header], $RES[cache-control: no-cache, private], append, 5xx
$URL[/source/*], $RES[cache-control: no-cache], set, 404
/secure/*.dat, $RES[x-custom], unset, 200
/*.mp4, $RES[Access-Control-Allow-Origin: example1.com], set
/*.mp4, $RES[Access-Control-Allow-Origin: example2.com], put
{Match}는 IP, GeoIP, Header, URL 4가지로 설정이 가능하다.
- IP $IP[...]로 표기하며 IP, IP Range, Bitmask, Subnet 네 가지 형식을 지원한다.
- GeoIP $IP[...]로 표기하며 반드시 GeoIP 가 설정되어 있어야 한다. 국가코드는 ISO 3166-1 alpha-2 와 ISO 3166-1 alpha-3 를 지원한다.
- Header $HEADER[Key : Value]로 표기한다. Value는 명확한 표현과 패턴을 지원한다. Value가 생략된 경우에는 Key에 해당하는 헤더의 존재유무를 조건으로 판단한다.
- URL $URL[...]로 표기하며 생략이 가능하다. 명확한 표현과 패턴을 인식한다.
{$REQ}와 {$RES}는 헤더변경 방법을 설정한다.
set
put
append
의 경우 {Key: Value}로 설정하며,
Value가 입력되지 않은 경우 빈 값(“”)이 입력된다.
unset
의 경우 {Key}만 입력한다.
{Action}은 set
, put
, append
, unset
4가지로 설정이 가능하다.
set
요청/응답 헤더에 설정되어 있는 Key와 Value를 헤더에 추가한다. 이미 같은 Key가 존재한다면 이전 값을 덮어쓴다.put
(set
과 유사하나) 같은 Key가 존재하면, 덮어쓰지 않고 새로운 라인으로 붙여 넣는다.append
(set
과 유사하나) 같은 Key가 존재하면, 기존의 Value와 설정된 Value사이에 Comma(,)로 구분하여 값을 결합한다.unset
요청/응답 헤더에 설정되어 있는 Key에 해당하는 헤더를 삭제한다.
{Condition}은 200이나 304같은 구체적인 응답 코드외에 2xx, 3xx, 4xx, 5xx처럼 응답코드 계열조건으로 설정한다. {Match}와 일치하더라도 {Condition}과 일치하지 않는다면 변경이 반영되지 않는다. {Condition}이 생략된 경우 응답코드를 검사하지 않는다.
압축¶
원본을 대신하여 컨텐츠를 압축하여 전송한다. Accept-Encoding 헤더 에 따라 컨텐츠를 구분하도록 설정되어 있어야 한다.
Accept-Encoding: gzip, deflate

비압축 파일을 실시간으로 압축하여 전송한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<Compression Method="gzip" Level="6" SourceSize="2-2048">OFF</Compression>
<Compression>
OFF (기본)
압축 기능을 사용하지 않는다.ON
압축 기능을 사용한다. 다음 속성을 지원한다.Method (기본: gzip)
압축 방식을 지정한다. gzip만 지원된다.Level (기본: 6)
압축 단계를 지정한다. 이 값은Method
에 따라 달라진다. gzip은 1~9까지 지정이 가능하다. 숫자가 작을수록 빠르지만 압축률이 나쁘고, 클수록 느리지만 압축률이 좋다.SourceSize (기본: 2-2048, 단위: KB)
원본 크기를 범위로 지정한다. 너무 작은 파일은 압축률이 떨어진다. 반대로 너무 큰 파일은 과도하게 CPU를 점유할 수 있다.
압축된 컨텐츠는 원본과 다른 컨텐츠로 인식/캐싱되며, 동일한 요청에 대해 다시 압축되지 않는다. 압축 대상은 /svc/{vhost}/compression.txt 에 지정한다. 정의된 순서대로 적용된다.
# /svc/www.example.com/compression.txt
# 구분자는 콤마( , ) 이다.
# {URL 조건}, {Method}, {Level} 순서로 표기한다.
/sample.css, no // 압축하지 않는다.
*.css // *.css 조건에 대해 기본 Method와 Level로 압축한다.
*.htm, gzip // *.htm 조건에 대해 gzip으로 압축한다. (기본 Level)
*.xml, , 9 // *.xml 조건에 대해 Level 9로 압축한다.*. (기본 Method)
*.js, gzip, 5 // *.js 조건에 대해 gzip (Level=5)으로 압축한다.
압축은 CPU자원을 많이 소모하는 기능이다. 다음은 파일 크기별 GZIP(Level: 9) 성능 테스트 결과이다.
OS
CentOS 6.3 (Linux version 2.6.32-279.el6.x86_64 (mockbuild@c6b9.bsys.dev.centos.org) (gcc version 4.4.6 20120305(Red Hat 4.4.6-4) (GCC) ) #1 SMP Fri Jun 22 12:19:21 UTC 2012)CPU
Intel(R) Xeon(R) CPU E5-2603 0 @ 1.80GHz (8 processors)RAM
8GBHDD
SAS 275GB X 5EA
크기 | 압축률(%) | 처리량 | 응답속도(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 |
<Compression>
이 활성화되어 있다면 원본 서버로 비압축 컨텐츠만을 요청한다.
비압축 컨텐츠란 원본 서버에 Accept-Encoding헤더를 명시하지 않고 보냈을 때의 응답을 의미한다.
만약 원본 서버가 비압축 컨텐츠 요청에 대해 Content-Encoding 헤더를 명시했다면 이미 압축된 것으로 간주하여 다시 압축하지 않는다.
주석
일부 컨텐츠가 이미 원본 서버에 의해 압축되어 있는 상태에서 <Compression>
조건에 해당한다면 중복 압축이 될 수 있다.
이 경우 문제가 될 수 있으므로 다음 정책을 따른다.
- 신규 컨텐츠라면 압축한다.
- 이미 원본 서버에 의해 압축되어 있다면 다시 압축하지 않는다.
- 원본 서버에 의해 압축되어 있지 않다면 해당 컨텐츠를 무효화하고, 압축을 진행한다.
7장. 원본서버¶
이 장에서는 STON과 원본서버의 관계에 대해 설명한다. 원본서버란 일반적으로 HTTP 규격을 준수하는 웹서버를 의미한다. 관리자라면 원본을 보호하기 위해 이번 장의 모든 내용을 숙지할 필요가 있다. 이를 바탕으로 원본장애에도 내구성을 갖춘 유연한 서비스를 구축할 수 있다.
원본서버는 보호되어야 한다. 장애의 종류가 다양한만큼 대처방안도 다양하다. 원본보호 정책을 적절히 구성하면 여유로운 점검시간을 가질 수 있다.
장애감지와 복구¶
Caching과정 중 원본서버에 장애가 발생하면 자동배제한다. 다시 안정화됐다고 판단하면 서비스에 투입한다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<ConnectTimeout>3</ConnectTimeout>
<ReceiveTimeout>10</ReceiveTimeout>
<Exclusion>3</Exclusion>
<Recovery Cycle="10" Uri="/" ResCode="0" Log="ON">5</Recovery>
<ConnectTimeout> (기본: 3초)
n초 이내에 원본서버와 접속이 이루어지지 않는 경우 접속실패로 간주한다.
<ReceiveTimeout> (기본: 10초)
정상적인 HTTP요청에도 불구하고 원본서버가 HTTP응답을 n초 동안 보내지 않는 경우 전송실패로 간주한다.
<Exclusion> (기본: 3회)
원본서버에서 연속적으로 n번 장애상황(
<ConnectTimeout>
또는<ReceiveTimeout>
)이 발생하면 해당 서버를 유효 원본서버 목록에서 배제한다. 배제 전 정상적인 통신이 이루어진다면 이 값은 다시 0으로 초기화된다.<Recovery> (기본: 5회)
Cycle
마다Uri
로 요청하여 원본서버가ResCode
로 연속적으로 n회 응답하면 해당 서버를 복구한다. 이 값을 0으로 설정하면 복구하지 않는다.Cycle (기본: 10초)
일정시간(초)마다 시도한다.Uri (기본: /)
요청을 보낼 UriResCode (기본: 0)
정상응답으로 처리할 응답코드. 0인 경우 응답코드와 상관없이 응답이 오면 성공으로 간주한다. 200으로 설정하면 응답코드가 반드시 200이어야 정상응답으로 처리한다. 콤마(,)를 사용하여 유효한 응답코드를 멀티로 설정한다. 200, 206, 404로 설정하면 응답코드가 이 중 하나인 경우 정상응답으로 처리한다.Log (기본: ON)
복구를 위해 사용된 HTTP Transaction을 Origin 로그 에 기록한다.
Health-Checker¶
장애감지와 복구 는 Caching 과정 중 발생하는 장애에 대응한다.
<Recovery>
는 응답코드를 받는 즉시 HTTP Transaction을 종료한다.
하지만 Health-Checker는 HTTP Transaction이 성공함을 확인한다.
# vhosts.xml - <Vhosts><Vhost>
<Origin>
<Address> ... </Address>
<HealthChecker ResCode="0" Timeout="10" Cycle="10"
Exclusion="3" Recovery="5" Log="ON">/</HealthChecker>
<HealthChecker ResCode="200, 404" Timeout="3" Cycle="5"
Exclusion="5" Recovery="20" Log="ON">/alive.html</HealthChecker>
</Origin>
<HealthChecker> (기본: /)
Health-Checker를 구성한다. 멀티로 구성이 가능하다. 값으로 Uri를 지정하며, XML예외 문자의 경우 CDATA를 사용한다.
ResCode (기본: 0)
올바른 응답코드 (콤마로 멀티 구성가능)Timeout (기본: 10초)
소켓연결부터 HTTP Transaction이 완료될 때까지 유효시간Cycle (기본: 10초)
실행주기Exclusion (기본: 3회)
연속 n회 실패 시 해당서버 배제Recovery (기본: 5회)
연속 n회 성공 시 해당서버 재투입Log (기본: ON)
HTTP Transaction을 Origin 로그 에 기록한다.
Health-Checker는 멀티로 구성할 수 있으며 클라이언트 요청과 상관없이 독립적으로 수행된다. 장애감지와 복구 나 다른 Health-Checker와도 정보를 공유하지 않고 자신만의 기준으로 배제와 투입을 결정한다.
원본주소 사용정책¶
원본주소(IP)는 다음 요소들에 의해 어떻게 사용될지 결정된다.
- 원본서버 주소 형식(IP 또는 Domain)과 보조주소
- 장애감지와 복구
- Health-Checker
서비스를 운영하다보면 원본주소가 배제/복구되는 일은 빈번하다. STON은 IP테이블을 기반으로 원본주소를 사용하며 origin-status API를 통해 정보를 제공한다.
원본주소를 IP로 설정한 경우 매우 간단하다.
- 설정변경 이외에 IP목록을 변화시키는 요인은 없다.
- TTL에 의해 IP주소가 만료되지 않는다.
- 장애/복구 모두 설정(IP주소)에 기반하여 동작한다.
원본주소를 Domain으로 설정하면 Resolving해서 IP를 얻어야 한다. ( DNS 로그 에 기록된다.) IP 목록은 동적으로 변경될 수 있으며 모든 IP는 TTL(Time To Live)동안만 유효하다.
- Domain은 주기적으로(1~10초) Resolving한다.
- Resolving결과를 통해 사용할 IP테이블을 구성한다.
- 모든 IP는 TTL만큼만 유효하며 TTL이 만료되면 사용하지 않는다.
- 같은 IP가 다시 Resolving되면 TTL을 갱신한다.
- IP테이블은 비어서는 안된다. (TTL이 만료되었더라도) 마지막 IP들은 삭제되지 않는다.
원본주소를 Domain으로 설정하여도 장애/복구는 IP기반으로 동작한다. 여기서 미묘한 점이 있다. DNS 클라이언트(=STON)는 Domain의 모든 IP 목록을 정확히 알 수 없다. 하지만 사용할 수 없는 IP들만으로 Domain을 구성할 경우 장애상태가 지속될 수 없다.
Domain주소 장애/복구 정책은 다음과 같다.
- (Domain에 대해) 알고 있는 모든 IP주소가 배제(Inactive)되면 해당 Domain주소가 배제된다.
- 신규 IP가 Resolving되더라도 Domain이 배제되어 있다면 IP주소는 처음부터 배제된다.
- 모든 IP가 TTL 만료되더라도 배제된 Domain상태는 풀리지 않는다.
- 배제된 Domain에 속한 IP주소가 하나라도 복구되어야 해당 Domain은 다시 활성화된다.
다소 복잡한 내용이므로 origin-status API를 통해 서비스 동작상태에 대해 이해도를 높이는 것이 좋다.
원본상태 모니터링¶
API를 통해 가상호스트의 원본상태를 모니터링한다.
http://127.0.0.1:10040/monitoring/origin // 모든 가상호스트
http://127.0.0.1:10040/monitoring/origin?vhost=www.example.com
결과는 JSON형식으로 제공된다.
{
"origin" :
[
{
"VirtualHost" : "example.com",
"Address" :
[
{ "1.1.1.1" : "Active" },
{ "1.1.1.2" : "Active" }
],
"Address2" : [ ],
"ActiveIP" :
[
{ "1.1.1.1" : 0 },
{ "1.1.1.2" : 0 }
] ,
"InactiveIP" : [ ]
},
{
"VirtualHost" : "foobar.com",
"Address" :
[
{ "origin.foobar.com" : "Active" }
],
"Address2" : [ ],
"ActiveIP" :
[
{ "5.5.5.5" : 21 },
{ "5.5.5.6" : 60 },
{ "5.5.5.7" : 37 }
],
"InactiveIP" :
[
{ "5.5.5.8" : 10 },
{ "5.5.5.9" : 184 }
]
}
]
}
VirtualHost
가상호스트 이름Address
원본서버 . 설정주소가 사용중이라면Active
, (장애발생으로) 사용하고 있지 않다면Inactive
로 표시된다.Address2
보조 원본주소 . 설정주소를 사용중이라면Active
, 사용하고 있지 않다면Inactive
로 표시된다.ActiveIP
사용 중인 IP목록과 TTL. 원본서버를 IP로 설정하면Address
와 동일한 IP에 TTL은 0으로 표시된다. Domain으로 설정하면 Resolving결과에 따른다. 다양한 IP와 TTL을 사용한다.InactiveIP
사용하지 않는 IP목록과 TTL. 사용하지 않더라도 복구 중이거나 HealthChecker에 의해 관리될 수 있다. 해당 주소는 TTL 동안 복구되지 않으면 삭제된다.
원본상태 초기화¶
API를 통해 가상호스트의 원본서버 배제/복구를 초기화한다. 또한 현재 사용 중인 세션을 재사용하지 않고 새롭게 연결을 생성한다.
http://127.0.0.1:10040/command/resetorigin // 모든 가상호스트
http://127.0.0.1:10040/command/resetorigin?vhost=www.example.com
과부하 판단¶
처음 요청되는 콘텐츠는 항상 원본서버에 요청해야 한다. 하지만 이미 Caching된 콘텐츠라면 좀 더 유연하게 대처할 수 있다. 원본서버가 과부하 상태라고 판단되면 갱신을 늦추어 원본부하를 높이지 않는다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<BusySessionCount>100</BusySessionCount>
<BusySessionCount> (기본: 100개)
원본서버와 HTTP트랜잭션을 진행 중인 세션 수가 일정개수를 넘으면 과부하 상태로 판단한다. 과부하 상태에서 만료된 컨텐츠를 갱신하기 위해 원본서버로 접속하지 않도록 TTL을 TTL (Time To Live) 중<OriginBusy>
만큼 연장한다. 무조건 원본서버로 요청이 가도록 하려면 이 값을 아주 크게 설정하면 된다.
원본 선택¶
원본서버 주소가 멀티(2개 이상)로 구성되어 있을 때 원본서버 선택정책을 설정한다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<BalanceMode>RoundRobin</BalanceMode>
<BalanceMode> (기본: RoundRobin)
RoundRobin (기본)
모든 원본서버가 균등하게 요청을 받도록 Round-Robin으로 동작한다. 연결된 Idle세션은 해당 서버로 요청이 필요할 때만 사용한다.Session
재사용할 수 있는 세션이 있다면 우선 사용한다. 신규 세션이 필요하면 Round-Robin으로 할당한다.Hash
컨텐츠를 Consistent Hashing 알고리즘에 따라 원본서버로 분산하여 요청한다. 서버가 선택되면 이미 연결된 세션을 재사용하며 없다면 신규로 접속한다.
/ | RoundRobin | Session |
---|---|---|
부하(요청) | 모든 서버가 부하를 균등하게 분배 | 반응성과 재사용성이 좋은 서버로 로드가 가중됨 |
연결비용 | 높음 (해당 서버의 순서가 되면 연결된 세션을 찾고 없으면 연결시도) | 낮음 (재사용할 수 있는 세션이 없을 때만 연결) |
재사용성 | 낮음 (서버 분배 우선) | 높음 (항상 연결된 세션을 우선 사용) |
세션수 | 많음 (각 서버마다 동시에 진행되는 HTTP 트랜잭션의 합) | 적음 (동시에 진행되는 HTTP 트랜잭션 만큼 세션 존재) |
세션 재사용¶
원본서버가 Keep-Alive를 지원한다면 연결된 세션은 항상 재사용된다. 하지만 세션을 재사용하여 보낸 요청에 대해 원본서버가 일방적으로 연결을 종료할 수 있다. 때문에 연결을 복구하느라 사용자 반응성이 늦어질 가능성이 있다. 특히 오랫동안 재사용하지 않은 세션의 경우 이러한 가능성은 더욱 높다. 이를 방지하기 위하여 n초 동안 재사용되지 않은 세션에 대해서 자동으로 연결을 종료하도록 설정한다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<ReuseTimeout>60</ReuseTimeout>
<ReuseTimeout> (기본: 60초)
일정 시간동안 사용되지 않은 원본세션은 종료한다. 0으로 설정하면 원본서버 세션을 재사용하지 않는다.
Range요청¶
한번에 다운로드 받는 컨텐츠 크기를 설정한다. 동영상처럼 앞 부분만이 주로 소비되는 컨텐츠의 경우 다운로드 크기를 제한하면 불필요한 원본 트래픽를 줄일 수 있다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<PartSize>0</PartSize>
<PartSize> (기본: 0 MB)
0보다 크면 클라이언트가 요청한 지점부터 설정크기(MB) 만큼 Range요청으로 다운로드 한다.
<PartSize>
를 사용하는 또 다른 이유는 디스크 공간을 절약하기 위함이다.
기본설정으로 STON은 원본크기의 파일을 디스크에 생성한다.
하지만 <PartSize>
가 0이 아니라면 다운로드 되는만큼만 파일을 분할하여 저장한다.
예를 들어 1시간짜리 영상(600MB)을 1분(10MB)만 시청한 경우에 디스크 공간을 10MB만 사용한다. 공간을 절약하는 장점은 있지만 파일이 분할되어 저장되기 때문에 디스크 부하가 조금 높아진다.
주석
최초 콘텐츠를 다운로드할 때 Content-Length를 알 수 없으므로 Range요청을 할 수 없다.
때문에 <PartSize>
가 설정되어 있다면 설정크기만큼만 다운로드 받고 연결을 종료한다.
전체 Range 초기화¶
일반적으로 원본서버로부터 처음 파일을 다운로드 할 때나 갱신확인 할 때는 다음과 같이 단순한 형태의 GET 요청을 보낸다.
GET /file.dat HTTP/1.1
하지만 원본서버가 일반적인 GET요청에 대하여 항상 파일을 변조하도록 설정되어 있다면 원본파일 그대로를 Caching할 수 없어서 문제가 될 수 있다.
가장 대표적인 예는 Apache 웹서버가 mod_h.264_streaming같은 외부모듈과 같이 구동되는 경우이다. Apache 웹서버는 GET요청에 대해서 항상 mod_h.264_streaming모듈을 통해서 응답한다. 클라이언트(이 경우에는 STON)는 원본파일 그대로가 아닌 모듈에 의해 변조된 파일을 서비스 받는다.
![]()
mod_h.264_streaming모듈은 항상 원본을 변조한다.
Range요청을 사용하면 모듈을 우회하여 원본을 다운로드할 수 있다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<FullRangeInit>OFF</FullRangeInit>
<FullRangeInit>
OFF (기본)
일반적인 HTTP요청을 보낸다.ON
0부터 시작하는 Range요청을 보낸다. Apache의 경우 Range헤더가 명시되면 모듈을 우회한다.GET /file.dat HTTP/1.1 Range: bytes=0-
최초로 파일 Caching할 때는 컨텐츠의 Range를 알지 못하므로 Full-Range(=0부터 시작하는)를 요청한다. 원본서버가 Range요청에 대해 정상적으로 응답(206 OK)하는지 반드시 확인해야 한다.
콘텐츠를 갱신할 때는 다음과 같이 If-Modified-Since 헤더가 같이 명시된다. 원본서버가 올바르게 304 Not Modified 로 응답해야 한다.
GET /file.dat HTTP/1.1
Range: bytes=0-
If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
주석
<FullRangeInit>
가 정상동작함을 확인한 웹서버들 목록.
- Microsoft-IIS/7.5
- nginx/1.4.2
- lighttpd/1.4.32
- Apache/2.2.22
클라이언트 요청 유지¶
원본에 요청할 때 클라이언트가 보낸 요청을 유지하도록 설정한다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<WholeClientRequest>OFF</WholeClientRequest>
<WholeClientRequest>
OFF (기본)
Caching-Key를 원본에 요청할 URL로 사용한다.ON
클라이언트가 요청한 URL로 원본에 요청한다.
Hit Ratio를 높이기 위해 다음 설정들을 통해 Caching-Key를 결정한다.
이에 따라 원본서버로 요청하는 URL과 Caching-Key가 다음과 같이 결정된다.
설정 | 클라이언트 요청 URL | 원본 요청URL / Caching-Key |
---|---|---|
대소문자 구분 OFF |
/Image/LOGO.png | /image/logo.png |
대소문자 구분 ON |
/Image/LOGO.png | /Image/LOGO.png |
QueryString 구분 OFF |
/view/list.php?type=A | /view/list.php |
QueryString 구분 ON |
/view/list.php?type=A | /view/list.php?type=A |
<WholeClientRequest>
를 ON
으로 설정하면 다음과 같이 Caching-Key와 상관없이 클라이언트가 보낸 URL을 그대로 원본에 보낸다.
설정 | 클라이언트 / 원본 요청 URL | Caching-Key |
---|---|---|
대소문자 구분 OFF |
/Image/LOGO.png | /image/logo.png |
대소문자 구분 ON |
/Image/LOGO.png | /Image/LOGO.png |
QueryString 구분 OFF |
/view/list.php?type=A | /view/list.php |
QueryString 구분 ON |
/view/list.php?type=A | /view/list.php?type=A |
POST 요청을 캐싱하는 경우 원본서버로 요청할 때 클라이언트가 보낸 POST요청의 Body데이터가 수정없이 전송된다.
주석
클라이언트가 보낸 URL을 그대로 보내기 때문에 Trimming 처럼 부가기능을 위해 붙여진 QueryString도 그대로 원본서버로 전달된다.
원본요청 기본 Header¶
Host 헤더¶
원본서버로 보내는 HTTP요청의 Host헤더를 설정한다. 별도로 설정하지 않은 경우 가상호스트 이름이 명시된다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<Host />
<Host>
원본서버로 보낼 Host헤더를 설정한다. 원본서버에서 80포트 이외의 포트로 서비스하고 있다면 반드시 포트 번호를 명시해야 한다.# server.xml - <Server><VHostDefault><OriginOptions> # vhosts.xml - <Vhosts><Vhost><OriginOptions> <Host>www.example2.com:8080</Host>
클라이언트가 보낸 Host헤더를 원본으로 보내고 싶은 경우 *로 설정한다.
User-Agent 헤더¶
원본서버로 보내는 HTTP요청의 User-Agent헤더를 설정한다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<UserAgent>STON</UserAgent>
<UserAgent> (기본: STON)
원본서버로 보낼 User-Agent헤더를 설정한다.
클라이언트가 보낸 User-Agent헤더를 원본으로 보내고 싶은 경우 *로 설정한다.
XFF(X-Forwarded-For) 헤더¶
클라이언트와 원본서버 사이에 STON이 위치하면 원본서버는 클라이언트 IP를 얻을 수 없다. 때문에 STON은 원본서버로 보내는 모든 HTTP요청에 X-Forwarded-For헤더를 명시한다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<XFFClientIPOnly>OFF</XFFClientIPOnly>
<XFFClientIPOnly>
OFF (기본)
클라이언트(IP: 128.134.9.1)가 보낸 XFF헤더에 클라이언트 IP를 추가한다. 클라이언트가 XFF헤더를 보내지 않았다면 클라이언트 IP만 명시된다.X-Forwarded-For: 220.61.7.150, 61.1.9.100, 128.134.9.1
ON
XFF헤더의 첫번째 주소만을 원본서버로 전송한다.X-Forwarded-For: 220.61.7.150
ETag 헤더 인식¶
원본서버에서 응답하는 ETag인식여부를 설정한다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<OriginalETag>OFF</OriginalETag>
<OriginalETag>
OFF (기본)
ETag헤더를 무시한다.ON
ETag를 인식하며 컨텐츠 갱신시 If-None-Match헤더를 추가한다.
원본요청 URL변경¶
캐싱을 목적으로 원본으로 보내는 HTTP요청의 URL을 변경한다.
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<URLRewrite>
<Pattern>/download/(.*)</Pattern>
<Replace>/#1</Replace>
</URLRewrite>
// Pattern : /download/1.3.4
// Replace : /1.3.4
<URLRewrite>
<Pattern>/img/(.*\.(jpg|png).*)</Pattern>
<Replace>/#1/STON/composite/watermark1</Replace>
</URLRewrite>
// Pattern : /img/image.jpg?date=20140326
// Replace : /image.jpg?date=20140326/STON/composite/watermark1
handling_http_requests_url_rewrite 와 같은 표현을 사용하지만 가상호스트마다 독립적으로 설정하기 때문에 가상호스트명을 입력하지 않는다.
주석
바이패스되는 HTTP요청의 URL은 변경할 수 없다.
<WholeClientRequest>
보다 우선한다.
원본요청 헤더변경¶
원본으로 HTTP요청을 보낼 때 조건에 따라 HTTP 헤더를 변경한다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<ModifyHeader FirstOnly="OFF">OFF</ModifyHeader>
<ModifyHeader>
OFF (기본)
변경하지 않는다.ON
헤더 변경조건에 따라 헤더를 변경한다.
헤더 변경시점은 HTTP 요청패킷이 완성되어 원본서버로 전송하기 직전에 수행된다. 단, Range헤더는 변조할 수 없다.
이 기능은 클라이언트 요청/응답 헤더 변경 의 하위 기능이다. 헤더변경에는 $ORGREQ 키워드를 사용한다.
# /svc/www.example.com/headers.txt
$URL[/*.mp4], $ORGREQ[x-media-type: video/mp4], set
$IP[1.1.1.1], $ORGREQ[user-agent: media_probe], put
*, $ORGREQ[If-Modified-Since], unset
*, $ORGREQ[If-None-Match], unset
주석
If-Modified-Since 헤더와 If-None-Match 헤더를 unset
하면 TTL이 만료된 컨텐츠는 항상 다시 다운로드 한다.
8장. 바이패스¶
이 장에서는 클라이언트 요청처리를 원본서버에게 위임하는 바이패스에 대해 설명한다. 바이패스는 조건과 동작으로 구분된다.
바이패스는 Caching정책보다 우선한다. 설계단계에서 Edge도입이 고려되지 않은 서비스라면 정적리소스와 동적리소스를 정교하게 구분해낼 수 없는 경우가 많다. 이런 경우 모든 클라이언트 요청을 바이패스하도록 구성한 뒤 로그에 기반하여 요청이 많은 콘텐츠만 Caching하도록 설정한다. 대개의 경우 몇 시간의 로그만으로 원본부하를 극적으로 낮출 수 있다. 10장. 모니터링 & 통계 에서 실시간 정보를 제공하는 이유도 서비스를 실시간 튜닝할 수 있도록 하기 위함이다.
바이패스는 아주 빠를뿐만 아니라 HTTP트랜잭션 단위로 동작한다. 아무리 개인화된 사이트라고 해도 대부분은 메인 페이지(.html)만 동적으로 변경될 뿐 나머지 99%는 정적인 리소스로 구성된다. 원본서버 동작에 맞출 수 있도록 원본요청 기본 Header 의 바이패스 버전이 별도로 존재한다.
No-Cache 요청 바이패스¶
클라이언트가 no-cache요청을 보냈다면 바이패스한다.
GET / HTTP/1.1
cache-control: no-cache 또는 cache-control:max-age=0
pragma: no-cache
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<BypassNoCacheRequest>OFF</BypassNoCacheRequest>
<BypassNoCacheRequest>
OFF (기본)
Cache모듈이 처리한다.ON
원본서버로 바이패스한다.
주석
이 설정은 클라이언트 동작(아마도 ctrl
+ F5
)에 의해 판단된다.
그러므로 대량의 바이패스가 원본에 부담을 줄 가능성이 있다.
GET/POST 바이패스¶
바이패스가 GET/POST요청의 기본동작이 되도록 설정할 수 있다. GET과 POST의 용도가 다른만큼 기본동작이 다름에 유의한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<BypassPostRequest>ON</BypassPostRequest>
<BypassGetRequest>OFF</BypassGetRequest>
<BypassPostRequest>
ON (기본)
POST요청을 원본서버로 바이패스한다.OFF
POST요청을 STON이 처리한다.
<BypassGetRequest>
OFF (기본)
GET요청을 STON이 처리한다.ON
GET요청을 원본서버로 바이패스한다.
가상호스트 ACL 과 동일한 조건을 모두 지원한다. 바이패스 예외조건은 /svc/{가상호스트 이름}/bypass.txt 에 설정한다.
# /svc/www.example.com/bypass.txt
$IP[192.168.2.1-255]
/index.html
cache나 bypass조건을 명확하게 명시하지 않은 경우 기본설정과 반대로 동작한다.
예를 들어 <BypassGetRequest>
이 ON
이라면 예외조건은 Caching목록이 된다.
헷갈릴 여지가 많다면 2번째 파라미터를 사용하여 보다 분명하게 조건을 설정할 수 있다.
# /svc/www.winesoft.co.kr/bypass.txt
$HEADER[cookie: *ILLEGAL*], cache // 항상 Caching처리
!HEADER[referer:] // 기본 설정에 따라 다름
!HEADER[referer] & !HEADER[user-agent], bypass // 항상 바이패스
$URL[/source/public.zip] // 기본 설정에 따라 다름
정리하면 우선순위는 다음과 같다.
- No-Cache 바이패스
- bypass.txt에 bypass라고 명시된 경우
- bypass.txt의 기본 설정
원본서버 고정¶
로그인 상태처럼 원본서버와 클라이언트가 반드시 1:1로 통신해야 하는 경우가 있다. GET/POST 바이패스 의 속성으로 원본서버를 고정시킬 수 있다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<BypassPostRequest OriginAffinity="ON">...</BypassPostRequest>
<BypassGetRequest OriginAffinity="ON">...</BypassGetRequest>
OriginAffinity
ON (기본)
클라이언트 요청이 항상 같은 서버로 바이패스되는 것을 보장한다. 단, 같은 소켓임을 보장하지는 않는다.바이패스해야 하는 원본서버와 연결된 모든 소켓이 끊어지는 상황이 발생할 수도 있다. 하지만 이런 경우에도 해당 서버로 새로운 소켓연결을 요청한다.
항상 같은서버로 바이패스된다.
바이패스하던 원본서버가 장애로 배제되거나 DNS에서 빠질 경우 새로운 서버로 바이패스된다.
OFF
클라이언트의 요청이 어느 서버로 바이패스되는지 보장할 수 없다.원본 선택 에 의해 따른다.
원본세션 고정¶
클라이언트 소켓마다 원본서버와 1:1로 바이패스 세션을 사용한다.

클라이언트가 원본세션을 소유한다.
GET/POST 바이패스 의 속성으로 원본세션을 고정시킬 수 있다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<BypassPostRequest Private="OFF">...</BypassPostRequest>
<BypassGetRequest Private="OFF">...</BypassGetRequest>
Private
ON
클라이언트 세션이 원본서버 전용세션을 사용하도록 동작한다. 항상 같은 서버로 요청이 바이패스 된다. 클라이언트와 원본서버 중 어느 한쪽이 세션을 종료되는 순간 상대방 세션 또한 종료됩니다.OFF (기본)
전용세션을 사용하지 않는다.
원본서버가 사용자의 로그인 정보를 세션에 기반하여 유지하는 경우처럼 클라이언트의 요청이 반드시 같은 소켓으로 처리되야 하는 경우 유용하다.
주석
자칫 너무 많은 요청을 Private
으로 바이패스하는 경우 클라이언트 수 만큼 원본서버에 연결되어 엄청난 부하를 줄 수 있다.
또한 이렇게 연결된 원본세션은 클라이언트가 소유하게 되므로 악의적인 공격상황에서 위험을 초래할 수도 있다.
Timeout¶
바이패스는 원본서버에서 동적으로 처리한 결과를 응답하는 경우가 많다. 이로 인해 처리 속도가 정적인 콘텐츠보다 느린 경우가 많다. 바이패스 전용 Timeout을 설정하여 섣부른 장애판단이 되지 않도록 한다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<BypassConnectTimeout>5</BypassConnectTimeout>
<BypassReceiveTimeout>300</BypassReceiveTimeout>
<BypassConnectTimeout> (기본: 5초)
바이패스를 위해 n초 이내에 원본서버와 접속이 이루어지지 않는 경우 접속실패로 처리한다.<BypassReceiveTimeout> (기본: 5초)
바이패스 중 원본서버의 응답이 n초 없을 경우 전송실패로 처리한다.
바이패스 헤더¶
원본요청 기본 Header 설정의 바이패스 적용여부를 설정한다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<UserAgent Bypass="OFF">...</UserAgent>
<Host Bypass="ON"/>
<XFFClientIPOnly Bypass="ON">...</XFFClientIPOnly>
Bypass
속성ON
설정된 헤더를 명시한다.OFF
클라이언트가 보낸 관련헤더를 명시한다.
Port 바이패스¶
특정 TCP포트의 모든 패킷을 원본서버로 바이패스한다. 가상호스트 전용설정이다.
# vhosts.xml - <Vhosts>
<Vhost Name="www.example">
<PortBypass>443</PortBypass>
<PortBypass Dest=”1935”>1935</PortBypass>
</Vhost>
<PortBypass>
지정된 포트로 입력된 모든 패킷을 원본서버의 같은 포트로 바이패스한다.Dest
속성으로 원본서버 포트를 설정한다.
예를 들어 443포트를 바이패스 한다면 클라이언트는 원본서버와 직접 SSL통신을 하는 효과를 가진다. 바이패스되는 포트는 절대 중복설정할 수 없다.
주석
구조적으로 Port 바이패스는 HTTP보다 하위 Layer인 TCP에서 이루어진다. 특정 가상호스트 하위에 Port 바이패스를 설정하는 이유는 통계를 수집할 주체가 필요하기 때문이다.
9장. HTTPS¶
이 장에서는 HTTPS 구성에 대해 설명한다. TLS 1.2까지 지원하며 SSL 2.0은 보안상의 이유로 업그레이드만 허용한다. HTTPS는 클라이언트와 STON구간에서만 사용된다. STON은 원본서버와 HTTPS로 통신하지 않는다. 왜냐하면 보안적으로나 성능적으로 STON이 HTTPS를 중계하는 것은 적절하지 않기 때문이다. 만약 원본서버와 반드시 HTTPS로 통신해야 한다면 Port 바이패스 를 권장한다.
서비스 구성¶
별도의 IP 또는 포트를 지정하지 않는 경우 기본으로 바인딩되는 서비스 주소는 “*:443” 이다. 전역설정(server.xml)에 설정한다.
# server.xml - <Server>
<Https>
<Cert>/usr/ssl/cert.pem</Cert>
<Key>/usr/ssl/certkey.pem</Key>
<CA>/usr/ssl/CA.pem</CA>
</Https>
<Https Listen="1.1.1.1:443">
<Cert>/usr/ssl_ip_port/cert.pem</Cert>
<Key>/usr/ssl_ip_port/certkey.pem</Key>
<CA>/usr/ssl_ip_port/CA.pem</CA>
</Https>
<Https Listen="*:886">
<Cert>/usr/ssl_port/cert.pem</Cert>
<Key>/usr/ssl_port/certkey.pem</Key>
<CA>/usr/ssl_port/CA.pem</CA>
</Https>
<Https>
HTTPS를 구성한다.<Cert>
서버 인증서<Key>
서버 인증서의 개인키. 암호화된 형식은 지원하지 않는다.<CA>
CA(Certificate Authority) 체인 인증서
같은 Port를 서비스하더라도 보다 명확한 표현이 우선한다.
예를 들어 위 예제처럼 NIC가 여러 개인 경우 1.1.1.1:443으로 들어온 클라이언트는 명시적 표현인 2번째(1.1.1.1:443) 인증서로 서비스되며 1.1.1.4:443으로 들어온 클라이언트는 일반적 표현인 1번째(생략 또는 *:443) 인증서로 서비스된다. 인증서파일을 같은 이름으로 덮어쓰기 하여도 Reload할 때 반영된다.
주석
인증서 포맷은 PEM(Privacy Enhanced Mail), 비대칭키 알고리즘은 RSA만 지원한다.
SSL/TLS 가속¶
CPU(AES-NI)를 통해 SSL/TLS를 가속한다. AES-NI를 지원하는 CPU인 경우 SSL/TLS에서 AES알고리즘을 우선적으로 사용하도록 동작한다. AES-NI가 인식된 경우 다음과 같이 Info.log에 기록된다.
AES-NI : ON (SSL/TLS accelerated)
관리자가 AES-NI 사용여부를 선택할 수 있다.
# server.xml - <Server><Cache>
<AES-NI>ON</AES-NI>
<AES-NI> (기본: ON)
AES-NI 사용여부를 선택한다.
CipherSuite 선택¶
지원하는 CipherSuites는 다음과 같다.
Cipher Suite | TLS1.2 | TLS1.1/1.0 | SSL3.0 |
---|---|---|---|
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02F) | O | ||
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xC027) | O | ||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xC014) | O | O | |
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xC013) | O | O | |
TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009C) | O | ||
TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003D) | O | ||
TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003C) | O | ||
TLS_RSA_WITH_AES_256_CBC_SHA (0x0035) | O | O | |
TLS_RSA_WITH_AES_128_CBC_SHA (0x002F) | O | O | |
TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000A) | O | O | |
TLS_RSA_WITH_RC4_128_SHA (0x0005) | O | ||
TLS_RSA_WITH_RC4_128_MD5 (0x0004) | O |
<Https>
의 CipherSuite
속성을 사용하면 사용할 CipherSuite를 설정할 수 있다.
# server.xml - <Server>
<Https CipherSuite="ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP">
<Cert>/usr/ssl/cert.pem</Cert>
<Key>/usr/ssl/certkey.pem</Key>
<CA>/usr/ssl/CA.pem</CA>
</Https>
CipherSuite
Apache mod_ssl의 SSL CipherSuite표현 을 따른다.
Forward Secrecy 를 보장하면 더 높은 보안성을 얻을 수 있다. (아래 링크 참조)
기본적으로 FS(Forward Secrecy)를 보장하는 CipherSuite를 우선적으로 선택한다.
# server.xml - <Server>
<Https FS="ON"> ... </Https>
FS
ON (기본)
Forward Secrecy를 보장하는 CipherSuite를 우선적으로 선택한다.OFF
ClientHello에 명시된 순서대로 선택한다.
FS
속성은 CipherSuite
속성보다 우선한다.
주석
성능상의 이유로 ECDHE만 지원한다. DHE는 지원하지 않는다.
CipherSuite 조회¶
CipherSuite 설정결과를 조회한다. CipherSuite표현식은 OpenSSL 1.0.0E 를 준수한다.
http://127.0.0.1:10040/monitoring/ssl?ciphersuite=...
결과는 JSON형식으로 제공된다.
{
"version": "2.0.0",
"method": "ssl",
"status": "OK",
"result":
[
{
"Name" : "AES128-SHA",
"Ver" : "SSLv3",
"Kx" : "RSA",
"Au" : "RSA",
"Enc" : "AES(128)",
"Mac" : "SHA1"
},
{
"Name" : "AES256-SHA",
"Ver" : "SSLv3",
"Kx" : "RSA",
"Au" : "RSA",
"Enc" : "AES(256)",
"Mac" : "SHA1"
}
]
}
멀티 Domain 구성¶
한 대의 서버에서 여러 서비스를 동시에 운영할 경우 SSL설정이 문제가 될 수 있다. 대부분의 Web/Cache서버들은 HTTP 요청의 Host헤더를 보고 어떤 가상호스트에서 서비스할 것인지 결정한다.

일반적 HTTPS통신
일반적으로 SSL은 클라이언트(Browser)가 자신이 접속하려는 서버 도메인명(winesoft.co.kr)을 인증서를 통해 확인하는 것으로 신원확인을 한다. 만약 인증서로 신원확인이 되지 않는다면(잘못된 인증서 또는 유효기간 만료 등) 다음과 같이 사용자에게 신뢰여부를 묻는다(아예 차단하는 경우도 있다). 신뢰는 클라이언트가 하는 것이므로 정상적인 신원확인이 안되어도 계속 진행하길 원한다면 SSL통신이 이루어진다.

사용자에게 판단을 맡긴다.
서버에서 SSL을 사용하는 가상호스트가 하나라면 문제가 되지 않는다. 하지만 여러 개의 가상호스트를 동시에 운영하는 서버에서는 문제가 될 수 있다. 왜냐하면 서버가 클라이언트에게 인증서를 전달할 때(“일반적 HTTPS통신”의 “2. 인증서 전달”) 클라이언트가 어떤 Host에 접속하려는지 알 수 없기 때문이다.
이 문제를 극복하는 대표적인 방법은 다음과 같다.
SNI (Server Name Indication)¶
SSL/TLS의 SNI(Server Name Indication) 확장 필드를 사용하는 방식이다. 이 기능은 처음 클라이언트가 서버에게 SSL 연결을 요청할 때 HTTP 요청의 Host헤더처럼 대상 가상호스트를 명시함으로써 가능하다. 현재까지 가장 우아한 방법이지만 일부 구버전 클라이언트에서 지원하지 않는다. 다음은 SNI를 지원하지 않는 클라이언트 목록이다. (출처: Wikipedia - Server Name Indication ).
- Internet Explorer (any version) on Windows XP or Internet Explorer 6 or earlier
- Safari on Windows XP
- BlackBerry Browser
- Windows Mobile up to 6.5
- Android default browser on Android 2.x[34] (Fixed in Honeycomb for tablets and Ice Cream Sandwich for phones)
- wget before 1.14
- Java before 1.7
현실적으로 SNI의 사용은 불가능하므 STON은 SNI를 지원하고 있지 않다.
Multi Certificate¶
인증서의에 여러 도메인을 넣거나 Wildcard(i.e. *.winesoft.co.kr)를 명시하여 하나의 인증서로 여러 도메인의 신원을 확인시킬 수 있는 방법이다.

하나의 인증서로 여러 Domain을 인증한다.
서비스 주체가 같다면 효과적인 방법이지만 무관하다면 같은 인증서를 공유하는 것은 현실적으로 어렵다. 이 방법은 인증서만 교체하면 되는 것이므로 STON에서 별도로 설정하실 것은 없다 [ DigiCert 참고].
Multi Port¶
SSL은 기본적으로 443포트를 사용한다. SSL포트를 중복되지 않는 포트로 설정하시면 인증서를 여러개 설치할 수 있다. 클라이언트에서는 다음과 같이 포트를 명시함으로써 SSL통신이 가능하다.
https://winesoft.co.kr:543/
STON에서는 다음과 같이 Listen속성에 포트를 명시하여 인증서를 여러개로 설정한다.
# server.xml - <Server>
<Https> ..A사 인증서.. </Https>
<Https Listen="*:543"> ..B사 인증서.. </Https>
<Https Listen="*:544"> ..C사 인증서.. </Https>
이 방법은 가장 경제적이기는하나 모든 웹페이지 링크에 HTTPS 포트를 명시해야 하는 문제가 있다.
Multi NIC¶
서버의 NIC가 여러개로 구성되어 있다면 NIC마다 IP를 별도로 할당할 수 있다. 그러므로 서버 IP마다 별도의 인증서를 설치하여 클라이언트가 접속한 서버IP에 기반하여 인증서를 결정하도록 설정한다. STON에서는 다음과 같이 Listen속성에 IP명시하여 인증서를 여러개로 설정한다.
# server.xml - <Server>
<Https Listen="10.10.10.10"> ..A사 인증서.. </Https>
<Https Listen="10.10.10.11"> ..B사 인증서.. </Https>
<Https Listen="10.10.10.12"> ..C사 인증서.. </Https>
이 방법은 가장 일반적으로 사용되는 방식이다.
주석
설정을 공유하면 IP주소로 인해 문제가 될 수 있다. 이런 경우 IP대신 NIC이름으로 설정한다.
# server.xml - <Server>
<Https Listen="eth0"> ... </Https>
<Https Listen="eth1"> ... </Https>
<Https Listen="eth2"> ... </Https>
프로토콜 구성¶
<Https>
마다 프로토콜을 구성한다.
# server.xml - <Server>
<Https TLS1.2="ON" TLS1.1="ON" TLS1.0="ON" SSL3.0="ON"> ... </Https>
TLS1.2 (기본: ON)
TLS1.2를 사용한다.TLS1.1 (기본: ON)
TLS1.1을 사용한다.TLS1.0 (기본: ON)
TLS1.0을 사용한다.SSL3.0 (기본: ON)
SSL3.0을 사용한다.
HSTS¶
HSTS(HTTP Strict Transport Security) 는 클라이언트 요청/응답 헤더 변경 를 이용해 손쉽게 구현이 가능하다.
# /svc/www.example.com/headers.txt
*, $RES[Strict-Transport-Security: max-age=31536000; includeSubDomains], set
Qualys SSL Server Test 에서는 HSTS가 적용된 사이트에 대해서만 A+등급을 부여한다.

STON v2.2부터는 A+를 받을 수 있다.
3부. 관리/운영¶
10장. 모니터링 & 통계¶
이 장에서는 모니터링과 통계에 대해 설명한다. 모니터링과 통계는 용도에 따라 서로 다르게 이해되는 경우가 많다. 하지만 서비스는 숫자로 이야기한다는 관점에서 둘은 같다.
여기서 가장 중요한 요소는 실시간성이다. 5분도 너무 길다. 실시간으로 서비스 상태변화를 볼 수 있어야 한다. 수 많은 정책이 적용과 동시에 효과를 내는지 즉시 알 수 있어야 한다. 모든 통계는 1초단위로 수집되며 최소 단위가 된다.
모든 통계는 가상호스트별로 따로 수집될 뿐만 아니라 실시간(1초), 5분 평균으로 제공된다. 고객이 통계를 보다 쉽게 분석, 가공할 수 있도록 JSON과 XML 포맷으로 제공한다.
http://127.0.0.1:10040/monitoring/realtime?type=[JSON 또는 XML]
http://127.0.0.1:10040/monitoring/average?type=[JSON 또는 XML]
realtime
1초 전 서비스 상태를 제공한다.average
5분 단위 통계를 제공한다.
수집범위¶
통계수집 범위를 설정한다.
# server.xml - <Server><VHostDefault>
# vhosts.xml - <Vhosts><Vhost>
<Stats>
<DirDepth>0</DirDepth>
<DirDepthAccum>OFF</DirDepthAccum>
<HttpsTraffic>OFF</HttpsTraffic>
<ClientLocal>OFF</ClientLocal>
<OriginLocal>OFF</OriginLocal>
</Stats>
<DirDepth> (기본: 0)
디렉토리별로 통계를 수집한다. 0으로 설정된 경우 모든 통계를 루트(/) 디렉토리로 수집한다. 1로 설정하면 통계는 첫 번째 Depth 디렉토리별로 수집된다.
<DirDepthAccum>
디렉토리별로 통계수집할 때 상위 디렉토리 통계 합산여부를 설정한다.
<DirDepth>
이 0이라면 이 설정은 무시된다.OFF (기본)
상위 디렉토리로 통계를 합산하지 않는다.ON
상위 디렉토리로 통계를 합산한다.
예를 들어,
<DirDepth>
이 2이고 모든 디렉토리에 동일하게 10만큼의 트래픽이 발생하고 있다고 가정한다.<DirDepthAccum>
이OFF
라면 좌측 그림처럼 트래픽이 발생하는 디렉토리별로 따로 통계가 수집된다.ON
이라면 우측 그림처럼 하위 디렉토리의 모든 통계가 부모 디렉토리로 누적된다.상위 디렉토리 누적통계
예를 들어 /img 디렉토리는 하위 디렉토리의 트래픽과 자신의 트래픽을 더한 30을 통계 값으로 가지며 이 트래픽은 부모 디렉토리로 합산된다.
<HttpsTraffic>
OFF (기본)
HTTPS트래픽을 SSL통계로만 수집한다.ON
HTTPS트래픽을 SSL과 HTTP양쪽 통계에 같이 수집한다.
기본적으로 SSL레이어를 통과하면 별도의 SSL 통계로 수집한다. HTTPS의 경우 상위 프로토콜에서 HTTP로 처리되기 때문에 보다 세세한 통계수집이 가능하다. 하지만 SSL통계와 HTTP통계 양쪽에 중복 통계수집이 되므로 HTTP통계만을 신뢰할 것을 권장한다.
<ClientLocal>
Loopback 클라이언트와 STON구간의 트래픽을 통계로 집계한다.
OFF (기본)
집계하지 않는다.ON
집계한다.
<OriginLocal>
STON구간과 Loopback 원본서버 구간의 트래픽을 통계로 집계한다.
OFF (기본)
집계하지 않는다.ON
집계한다.
호스트 종합통계¶
호스트 통계는 가장 상위 개념의 통계로 서비스하는 모든 가상호스트의 통계를 종합한다. 같은 통계를 JSON과 XML형식으로 제공한다.
{ <Host
"Host": Version="2.0.0"
{ Name="localhost"
"Version":"2.0.0", State="Healthy"
"Name":"localhost", Uptime="155986"
"State":"Healthy", OriginSession="32"
"Uptime":155996, OriginActiveSession="20"
"OriginSession":33, OriginInbound="1140741"
"OriginActiveSession":20, OriginOutbound="10059"
"OriginInbound":688177, OriginReqCount="42"
"OriginOutbound":14184, OriginResTotalCount="42"
"OriginReqCount":62, OriginResTotalTimeRes="5071"
"OriginResTotalCount":62, OriginResTotalTimeComplete="10288"
"OriginResTotalTimeRes":2375, OriginRes2xxCount="19"
"OriginResTotalTimeComplete":2509, OriginRes2xxTimeRes="9989"
"OriginRes2xxCount":54, OriginRes2xxTimeComplete="21521"
"OriginRes2xxTimeRes":2327, OriginRes3xxCount="23"
"OriginRes2xxTimeComplete":2481, OriginRes3xxTimeRes="1008"
"OriginRes3xxCount":8, OriginRes3xxTimeComplete="1008"
"OriginRes3xxTimeRes":2700, OriginRes4xxCount="0"
"OriginRes3xxTimeComplete":2700, OriginRes4xxTimeRes="0"
"OriginRes4xxCount":0, OriginRes4xxTimeComplete="0"
"OriginRes4xxTimeRes":0, OriginRes5xxCount="0"
"OriginRes4xxTimeComplete":0, OriginRes5xxTimeRes="0"
"OriginRes5xxCount":0, OriginRes5xxTimeComplete="0"
"OriginRes5xxTimeRes":0, ClientSession="165"
"OriginRes5xxTimeComplete":0, ClientActiveSession="80"
"ClientSession":155, ClientInbound="14792"
"ClientActiveSession":80 ClientOutbound="1981700"
"ClientInbound":35748, ClientReqCount="64"
"ClientOutbound":972906, ClientResTotalCount="64"
"ClientReqCount":152, ClientResTotalTimeRes="5535"
"ClientResTotalCount":152, ClientResTotalTimeComplete="6840"
"ClientResTotalTimeRes":1411, ClientRes2xxCount="44"
"ClientResTotalTimeComplete":1479, ClientRes2xxTimeRes="8050"
"ClientRes2xxCount":93, ClientRes2xxTimeComplete="9943"
"ClientRes2xxTimeRes":2305, ClientRes3xxCount="20"
"ClientRes2xxTimeComplete":2409, ClientRes3xxTimeRes="5"
"ClientRes3xxCount":59, ClientRes3xxTimeComplete="15"
"ClientRes3xxTimeRes":3, ClientRes4xxCount="0"
"ClientRes3xxTimeComplete":13, ClientRes4xxTimeRes="0"
"ClientRes4xxCount":0, ClientRes4xxTimeComplete="0"
"ClientRes4xxTimeRes":0, ClientRes5xxCount="0"
"ClientRes4xxTimeComplete":0, ClientRes5xxTimeRes="0"
"ClientRes5xxCount":0, ClientRes5xxTimeComplete="0"
"ClientRes5xxTimeRes":0, RequestHitRatio="6923"
"ClientRes5xxTimeComplete":0, ByteHitRatio="4243">
"RequestHitRatio":6387, <HttpCountSum
"ByteHitRatio":2926, OriginReqCount="0"
"HttpCountSum" : OriginResTotalCount="0"
{ OriginRes2xxCount="0"
"OriginReqCount" : 0, OriginRes3xxCount="0"
"OriginResTotalCount" : 0, OriginRes4xxCount="0"
"OriginRes2xxCount" : 0, OriginRes5xxCount="0"
"OriginRes3xxCount" : 0, ClientReqCount="0"
"OriginRes4xxCount" : 0, ClientResTotalCount="0"
"OriginRes5xxCount" : 0, ClientRes2xxCount="0"
"ClientReqCount" : 0, ClientRes3xxCount="0"
"ClientResTotalCount" : 0, ClientRes4xxCount="0"
"ClientRes2xxCount" : 0, ClientRes5xxCount="0"/>
"ClientRes3xxCount" : 0, <HttpRequestHitSum
"ClientRes4xxCount" : 0, TCP_NONE="0"
"ClientRes5xxCount" : 0 TCP_HIT="0"
}, TCP_IMS_HIT="0"
"HttpRequestHitSum" : TCP_REFRESH_HIT="0"
{ TCP_REF_FAIL_HIT="0"
"TCP_NONE" : 0, TCP_NEGATIVE_HIT="0"
"TCP_HIT" : 0, TCP_REDIRECT_HIT="0"
"TCP_IMS_HIT" : 0, TCP_MISS="0"
"TCP_REFRESH_HIT" : 0, TCP_REFRESH_MISS="0"
"TCP_REF_FAIL_HIT" : 0, TCP_CLIENT_REFRESH_MISS="0"
"TCP_NEGATIVE_HIT" : 0, TCP_DENIED="0"
"TCP_REDIRECT_HIT" : 0, TCP_ERROR="0"/>
"TCP_MISS" : 0, <FileSystem>
"TCP_REFRESH_MISS" : 0, <RequestHitRatio>0</RequestHitRatio>
"TCP_CLIENT_REFRESH_MISS" : 0, <ByteHitRatio>0</ByteHitRatio>
"TCP_DENIED" : 0, <Outbound>0</Outbound>
"TCP_ERROR" : 0 <Session>0</Session>
}, </FileSystem>
"FileSystem": <System> ... </System>
{ <VirtualHost> ... </VirtualHost>
"RequestHitRatio":0, <VirtualHost> ... </VirtualHost>
"ByteHitRatio":0, <VirtualHost> ... </VirtualHost>
"Outbound":0, <View> ... </View>
"Session":0 <View> ... </View>
}, </Host>
"System":{ ... },
"VirtualHost": [ ... ]
"View": [ ... ]
}
}
Version
STON 버전Name
호스트이름. 설정하지 않았다면 시스템 이름을 보여준다.State
서비스 상태. (Healthy=정상 서비스, Inactive=라이센스 비활성화, Emergency)Uptime (단위: 초)
서비스 실행시간OriginSession
원본세션 수OriginActiveSession
전송 중인 원본세션 수OriginInbound (단위: Bytes, 평균)
원본서버부터 받은 양OriginReqCount (평균)
원본서버로 보낸 요청횟수OriginOutbound (단위: Bytes, 평균)
원본서버로 보낸 양OriginResTotalCount (평균)
원본서버 응답횟수OriginResTotalTimeRes (단위: 0.01ms, 평균)
원본서버 응답시간 (HTTP요청 전송 ~ HTTP응답 첫 수신)OriginResTotalTimeComplete (단위: 0.01ms, 평균)
원본서버 HTTP 트랜잭션 완료시간 (HTTP요청 전송 ~ HTTP응답 완료)OriginRes2xxCount (평균)
원본서버 2xx응답횟수OriginRes2xxTimeRes (단위: 0.01ms, 평균)
원본서버 2xx응답시간OriginRes2xxTimeComplete (단위: 0.01ms, 평균)
원본서버 2xx 트랜잭션 완료시간OriginRes3xxCount (평균)
원본서버 3xx응답횟수OriginRes3xxTimeRes (단위: 0.01ms, 평균)
원본서버 3xx응답시간OriginRes3xxTimeComplete (단위: 0.01ms, 평균)
원본서버 3xx 트랜잭션 완료시간OriginRes4xxCount (평균)
원본서버 4xx응답횟수OriginRes4xxTimeRes (단위: 0.01ms, 평균)
원본서버 4xx응답시간OriginRes4xxTimeComplete (단위: 0.01ms, 평균)
원본서버 4xx 트랜잭션 완료시간OriginRes5xxCount (평균)
원본서버 5xx응답횟수OriginRes5xxTimeRes (단위: 0.01ms, 평균)
원본서버 5xx응답시간OriginRes5xxTimeComplete (단위: 0.01ms, 평균)
원본서버 5xx 트랜잭션 완료시간ClientSession
클라이언트 세션 수ClientActiveSession
전송 중인 클라이언트 세션 수ClientInbound (단위: Bytes, 평균)
클라이언트로부터 받은 양ClientOutbound (단위: Bytes, 평균)
클라이언트로에게 보낸 양ClientReqCount (평균)
클라이언트로 받은 요청횟수ClientResTotalCount (평균)
클라이언트 응답횟수ClientResTotalTimeRes (단위: 0.01ms, 평균)
클라이언트 응답시간 (HTTP요청 수신 ~ HTTP응답 전송)ClientResTotalTimeComplete (단위: 0.01ms, 평균)
클라이언트 HTTP 트랜잭션 완료시간 (HTTP요청 수신 ~ HTTP응답 완료)ClientRes2xxCount (평균)
클라이언트 2xx응답횟수ClientRes2xxTimeRes (단위: 0.01ms, 평균)
클라이언트 2xx응답시간ClientRes2xxTimeComplete (단위: 0.01ms, 평균)
클라이언트 2xx 트랜잭션 완료시간ClientRes3xxCount (평균)
클라이언트 3xx응답횟수ClientRes3xxTimeRes (단위: 0.01ms, 평균)
클라이언트 3xx응답시간ClientRes3xxTimeComplete (단위: 0.01ms, 평균)
클라이언트 3xx 트랜잭션 완료시간ClientRes4xxCount (평균)
클라이언트 4xx응답횟수ClientRes4xxTimeRes (단위: 0.01ms, 평균)
클라이언트 4xx응답시간ClientRes4xxTimeComplete (단위: 0.01ms, 평균)
클라이언트 4xx 트랜잭션 완료시간ClientRes5xxCount (평균)
클라이언트 5xx응답횟수ClientRes5xxTimeRes (단위: 0.01ms, 평균)
클라이언트 5xx응답시간ClientRes5xxTimeComplete (단위: 0.01ms, 평균)
클라이언트 5xx 트랜잭션 완료시간RequestHitRatio (단위: 0.01%, 평균)
Hit율. 캐싱객체가 생성되어 있고 해당 객체가 초기화되어 있다면 Hit이다. 반대로 캐싱객체가 없거나 해당 객체가 원본서버로부터 초기화되지 않았다면 Hit로 치지 않는다. 응답코드와 Hit율은 관련이 없다.HTTP와 File I/O는 가상호스트를 공유한다.
Apache를 통해 접근되는 File I/O의 RequestHitRatio는 0%이 된다. 하지만 HTTP Server의 경우 File I/O에 의해 캐싱된 파일을 접근하기 때문에 100%의 RequestHitRatio를 가진다. ByteHitRatio의 경우 원본 Inbound대비 Http outbound, File I/O outbound로 각각 계산된다.
ByteHitRatio (단위: 0.01%, 평균)
원본서버 대비 클라이언트 전송률.(클라이언트 Outbound - 원본서버 Inbound) / 클라이언트 Outbound
원본서버가 훨씬 빠른 속도를 가지고 있거나 클라이언트 세션이 금방 끊어진다면 음수가 된다.
FileSystem
독립적인 FileSystem 통계로 다른 통계 수치에 취합되지 않는다.RequestHitRatio (단위: 0.01%, 평균)
File I/O를 통한 Hit율ByteHitRatio (단위: 0.01%, 평균)
원본서버 대비 File I/O 전송률Outbound (단위: Bytes, 평균)
File I/O로 서비스한 데이터 크기Session (평균)
File I/O 진행 중인 Thread 수
주석
5분 통계에서만 제공되는 항목.
HttpCountSum
HTTP 트랜잭션의 총 개수HttpRequestHitSum
캐시 HIT 결과
System 통계¶
시스템 및 전역자원 통계를 JSON과 XML형식으로 제공한다.
"System": <System>
{ <CPU
"CPU": Kernel="689"
{ User="1316"
"Kernel":689, Idle="7993"
"User":1316, ProcKernel="570"
"Idle":7993, ProcUser="1216"
"ProcKernel":570, Nice="0"
"ProcUser":1216, IOWait="52"
"Nice":0, IRQ="10"
"IOWait":52, SoftIRQ="12"
"IRQ":10, Steal="0" />
"SoftIRQ":12, <Mem Free="5914644" STON="9785800"/>
"Steal":0 <Storage>
}, <Disk
"Mem": Path="/cache1"
{ Status="Normal"
"Free":5914644, Read="23"
"STON":9785800 ReadMerged="0"
}, ReadSectors="344"
"Storage": ReadTime="117"
{ Write="24"
"Disk": WriteMerged="93"
[ WriteSectors="936"
{ WriteTime="256"
"Path":"/cache1", IOProgress="0"
"Status":"Normal", IOTime="173"
"Read":23, IOWeightedTime="373"/>
"ReadMerged":0, <Disk
"ReadSectors":344, Path="/cache2"
"ReadTime":117, Status="Normal"
"Write":24, Read="27"
"WriteMerged":93, ReadMerged="1"
"WriteSectors":936, ReadSectors="488"
"WriteTime":256, ReadTime="144"
"IOProgress":0, Write="24"
"IOTime":173, WriteMerged="86"
"IOWeightedTime":373 WriteSectors="880"
}, WriteTime="254"
{ IOProgress="0"
"Path":"/cache2", IOTime="189"
"Status":"Normal", IOWeightedTime="380"/>
"Read":27, </Storage>
"ReadMerged":1, <ServerSocket
"ReadSectors":488, Total="42"
"ReadTime":144, Established="2"
"Write":24, Accepted="1"
"WriteMerged":86, Closed="0"/>
"WriteSectors":880, <ClientSocket
"WriteTime":254, Total="1"
"IOProgress":0, Established="0"
"IOTime":189, Connected="0"
"IOWeightedTime":380 Closed="0"/>
} <TCPSocket
] Established="30"
}, Timewait="2"
"ServerSocket": Orphan="0"
{ Alloc="0"
"Total":42, Mem="20"/>
"Established":1, <EQ>0</EQ>
"Accepted":0, <RQ>1000000</RQ>
"Closed":0 <WaitingFiles2Write>0</WaitingFiles2Write>
}, <ServiceAccess Allow="60" Deny="2"/>
"ClientSocket": <SystemLoadAverage Min1="0" Min5="0" Min15="0"/>
{ <URLRewrite>57</URLRewrite>
"Total":1, </System>
"Established":0,
"Connected":0,
"Closed":0
},
"TCPSocket":
{
"Established":30,
"Timewait":2,
"Orphan":0,
"Alloc":0,
"Mem":20
},
"EQ":0,
"RQ":1000000,
"WaitingFiles2Write":0,
"ServiceAccess":{"Allow":60, "Deny":2}
"SystemLoadAverage":
{
"Min1":0,
"Min5":0,
"Min15":0
},
"URLRewrite":57
}
CPU (단위: 0.01%)
CPU사용량. 전체 CPU사용량은 Kernel + User로 계산해야 한다.Kernel
CPU(Kernel) 사용량User
CPU(User) 사용량Idle
사용되지 않는 CPU량ProcKernel
STON이 사용하는 CPU(Kernel) 사용량ProcUser
STON이 사용하는 CPU(User) 사용량Nice
niced processes executing in user modeIOWait
waiting for I/O to completeIRQ
servicing interruptsSoftIRQ
servicing softirqsSteal
involuntary wait
Mem (단위: Bytes)
메모리 사용량. -Free
시스템 Free 메모리 크기 -STON
STON이 사용하는 메모리 크기Disk
디스크 성능지표Path
디스크 경로Status
디스크 상태 (Normal: 정상동작, Invalid: 장애로 배제됨, Unmounted: 관리자에 의해 Unmount됨)Read
읽기 성공 횟수ReadMerged
읽기가 병합된 횟수ReadMerged
읽은 섹터 수ReadTime (단위: ms)
읽기 소요시간Write
쓰기 성공 횟수WriteMerged
쓰기가 병합된 횟수WriteSectors
써진 섹터 수WriteTime (단위: ms)
쓰기 소요시간IOProgress
진행 중인 IO개수IOTime (단위: ms)
IO 소요시간IOWeightedTime (단위: ms)
IO 소요시간(가중치 적용)
ServerSocket
서버 소켓(클라이언트와 STON 구간) 정보Total
전체 서버소켓 수Established
연결된 상태의 서버소켓 수Accepted
새롭게 연결된 서버소켓 수Closed
연결이 종료된 서버소켓 수
ClientSocket
클라이언트 소켓(STON과 원본서버 구간) 정보Total
전체 클라이언트소켓 수Established
연결된 상태의 클라이언트소켓 수Connected
새롭게 연결된 클라이언트소켓 수Closed
연결이 종료된 클라이언트소켓 수
TCPSocket
시스템(OS)이 제공하는 TCP상태 정보Established
Established상태의 TCP 연결개수Timewait
TIME_WAIT 상태의 TCP 연결개수Orphan
아직 file handle에 attach되지 않은 TCP 연결Alloc
할당된 TCP 연결Mem
undocumented
EQ
STON Framework에서 아직 처리되지 않은 Event개수RQ
최근 서비스된 컨텐츠 참조 큐에 저장된 Event 개수WaitingFiles2Write
디스크에 쓰기 대기중인 파일개수ServiceAccess
ServiceAccess에 의해 허가(Allow), 거부(Deny)된 소켓 수SystemLoadAverage
System Load Average의 1분/5분/15분 평균URLRewrite
URL전처리에 의해 변환이 성공한 횟수
가상호스트 통계¶
가상호스트별로 통계가 제공된다. 가상호스트 통계는 HTTP전송(디렉토리 별), URL바이패스, 포트바이패스, SSL로 구분된다.
"VirtualHost": <VirtualHost
[ Name="image.11st.co.kr"
{ Uptime="155956"
"Name":"image.11st.co.kr", OriginSession="12"
"Uptime":155966, OriginActiveSession="6"
"OriginSession":12, OriginInbound="106914"
"OriginActiveSession":6, OriginOutbound="3238"
"OriginInbound":169, OriginReqCount="42"
"OriginOutbound":269, OriginResTotalCount="13"
"OriginReqCount":62, OriginResTotalTimeRes="1553"
"OriginResTotalCount":1, OriginResTotalTimeComplete="6630"
"OriginResTotalTimeRes":3300, OriginRes2xxCount="1"
"OriginResTotalTimeComplete":3300, OriginRes2xxTimeRes="3300"
"OriginRes2xxCount":0, OriginRes2xxTimeComplete="69300"
"OriginRes2xxTimeRes":0, OriginRes3xxCount="12"
"OriginRes2xxTimeComplete":0, OriginRes3xxTimeRes="1408"
"OriginRes3xxCount":1, OriginRes3xxTimeComplete="1408"
"OriginRes3xxTimeRes":3300, OriginRes4xxCount="0"
"OriginRes3xxTimeComplete":3300, OriginRes4xxTimeRes="0"
"OriginRes4xxCount":0, OriginRes4xxTimeComplete="0"
"OriginRes4xxTimeRes":0, OriginRes5xxCount="0"
"OriginRes4xxTimeComplete":0, OriginRes5xxTimeRes="0"
"OriginRes5xxCount":0, OriginRes5xxTimeComplete="0"
"OriginRes5xxTimeRes":0, ClientSession="30"
"OriginRes5xxTimeComplete":0, ClientActiveSession="12"
"ClientSession":26, ClientInbound="4113"
"ClientActiveSession":16, ClientOutbound="895937"
"ClientInbound":13968, ClientReqCount="64"
"ClientOutbound":110398, ClientResTotalCount="18"
"ClientReqCount":152, ClientResTotalTimeRes="666"
"ClientResTotalCount":52, ClientResTotalTimeComplete="4377"
"ClientResTotalTimeRes":94, ClientRes2xxCount="10"
"ClientResTotalTimeComplete":107, ClientRes2xxTimeRes="1200"
"ClientRes2xxCount":1, ClientRes2xxTimeComplete="7870"
"ClientRes2xxTimeRes":4700, ClientRes3xxCount="8"
"ClientRes2xxTimeComplete":4800, ClientRes3xxTimeRes="0"
"ClientRes3xxCount":51, ClientRes3xxTimeComplete="12"
"ClientRes3xxTimeRes":3, ClientRes4xxCount="0"
"ClientRes3xxTimeComplete":15, ClientRes4xxTimeRes="0"
"ClientRes4xxCount":0, ClientRes4xxTimeComplete="0"
"ClientRes4xxTimeRes":0, ClientRes5xxCount="0"
"ClientRes4xxTimeComplete":0, ClientRes5xxTimeRes="0"
"ClientRes5xxCount":0, ClientRes5xxTimeComplete="0"
"ClientRes5xxTimeRes":0, RequestHitRatio="10000"
"ClientRes5xxTimeComplete":0, ByteHitRatio="8806">
"RequestHitRatio":10000, <FileSystem>
"ByteHitRatio":9984, <RequestHitRatio>0</RequestHitRatio>
"FileSystem": <ByteHitRatio>0</ByteHitRatio>
{ <Outbound>0</Outbound>
"RequestHitRatio":0, <Session>0</Session>
"ByteHitRatio":0, </FileSystem>
"Outbound":0, <Memory>784786700</Memory>.
"Session":0 <SecuredMemory>0</SecuredMemory>.
}, <Disk> ... </Disk>
"Memory":785740769, <Session> ... </Session>
"SecuredMemory":0, <Dims> ... </Dims>
"Disk": { ... }, <Compression> ... </Compression>
"Session": { ... }, <File Total="458278" Opened="15" Instance="458292"/>
"Dims": { ... }, <Cached> ... </Cached>
"Compression": { ... }, <CacheFileEvent> ... </CacheFileEvent>
"FileTotal":458308, <WaitingFiles2Delete>1087593</WaitingFiles2Delete>
"FileOpened":15, <CacheFileEvent Create=\"%u\" Swap=\"%u\" Erase=\"%u\" Purge=\"%u\" Expire=\"%u\" />
"FileInstance":458320, <ClientHttpReqBypass Sum="8100">27</ClientHttpReqBypass>
"Cached": { ... }, <ClientHttpReqDenied Sum="400">1</ClientHttpReqDenied>
"CacheFileEvent": { ... }, <OriginTraffic> ... </OriginTraffic>
"WaitingFiles2Delete":1087595, <PortBypass> ... </PortBypass>
"ClientHttpReqBypassSum":8100, <ClientTraffic> ... </ClientTraffic>
"ClientHttpReqBypass":27, <UrlBypass> ... </UrlBypass>
"ClientHttpReqDeniedSum":400, </VirtualHost>
"ClientHttpReqDenied":1, <VirtualHost> ... </VirtualHost>
"OriginTraffic": { ... }, <VirtualHost> ... </VirtualHost>
"PortBypass": { ... }, <VirtualHost> ... </VirtualHost>
"ClientTraffic": { ... },
"UrlBypass": { ... }
},
...
]
Memory (단위: Bytes)
메모리에 적재된 컨텐츠 양SecuredMemory (단위: Bytes)
메모리에서 삭제한 컨텐츠 양Disk
디스크 정보Session
세션 정보Dims
DIMS변환 통계Compression
압축 통계FileTotal
전체파일 개수FileOpened
열려져 있는 로컬파일 개수FileInstance
캐싱파일 개수Cached
캐싱 정보CacheFileEvent
캐싱파일 이벤트WaitingFiles2Delete
삭제대기 중인 파일개수ClientHttpReqBypass
바이패스한 클라이언트 HTTP요청 횟수ClientHttpReqDenied
HTTP요청이 차단된 횟수OriginTraffic
원본서버 트래픽 통계PortBypass
포트 바이패스 트래픽 통계ClientTraffic
클라이언트 트래픽 통계UrlBypass
URL매칭 또는<BypassNoCacheRequest>
를 통해 원본서버로변환 통계되는 HTTP트래픽 통계
주석
5분 통계에서만 제공되는 항목.
ClientHttpReqBypassSum
바이패스되는 HTTP요청의 총 개수ClientHttpReqDeniedSum
Deny되는 HTTP요청의 총 개수
디스크 통계¶
가상호스트가 사용하는 디스크통계를 제공한다.
"Disk": <Disk>
{ <TotalSize>22003701435</TotalSize>
"TotalSize":22004057982, <Create>1</Create>
"Create":0, <Open>10</Open>
"Open":1, <Delete>0</Delete>
"Delete":0, <ReadCount>9</ReadCount>
"ReadCount":1, <ReadSize>735726</ReadSize>
"ReadSize":104744, <WriteCount>1</WriteCount>
"WriteCount":0, <WriteSize>157145</WriteSize>
"WriteSize":0, <Distribution
"Distribution": U1K="45725"
{ U2K="192523"
"U1K="45725, U4K="137055"
"U2K="192523, U8K="39740"
"U4K="137055, U16K="13408"
"U8K="39740, U32K="12303"
"U16K="13408, U64K="11462"
"U32K="12303, U128K="2560"
"U64K="11462, U256K="22"
"U128K="2560, U512K="0"
"U256K="22, U1M="45725"
"U512K="0, U2M="192523"
"U1M="45725, U4M="137055"
"U2M="192523, U8M="39740"
"U4M="137055, U16M="13408"
"U8M="39740, U32M="12303"
"U16M="13408, U64M="11462"
"U32M="12303, U128M="2560"
"U64M="11462, U256M="22"
"U128M="2560, U512M="0"
"U256M="22, U1G="0"
"U512M="0, U2G="0"
"U1G="0, U4G="0"
"U2G="0, U8G="0"
"U4G="0, U16G="0"
"U8G="0, O16G="0" />
"U16G":0, </Disk>
"O16G":0
}
}
TotalSize (단위: Bytes)
로컬파일 크기 합Create
로컬파일 생성 횟수Open
로컬파일 Open 횟수Delete
로컬파일 삭제 횟수ReadCount
로컬파일에서 Read한 횟수ReadSize (단위: Bytes)
로컬파일에서 Read한 크기WriteCount
로컬파일에서 Write한 횟수WriteSize (단위: Bytes)
로컬파일에서 Write한 크기Distribution
로컬파일 크기별 분포U1K
1KB 미만 파일 개수U2K
2KB 미만 파일 개수U4K
4KB 미만 파일 개수U8K
8KB 미만 파일 개수U16K
16KB 미만 파일 개수U32K
32KB 미만 파일 개수U64K
64KB 미만 파일 개수U128K
128KB 미만 파일 개수U256K
256KB 미만 파일 개수U512K
512KB 미만 파일 개수U1M
1MB 미만 파일 개수U2M
2MB 미만 파일 개수U4M
4MB 미만 파일 개수U8M
8MB 미만 파일 개수U16M
16MB 미만 파일 개수U32M
32MB 미만 파일 개수U64M
64MB 미만 파일 개수U128M
128MB 미만 파일 개수U256M
256MB 미만 파일 개수U512M
512MB 미만 파일 개수U1G
1GB 미만 파일 개수U2G
2GB 미만 파일 개수U4G
4GB 미만 파일 개수U8G
8GB 미만 파일 개수U16G
16GB 미만 파일 개수O16G
16GB 이상 파일 개수
세션 통계¶
가상호스트가 사용하는 디스크통계를 제공한다.
"Session": <Session
{ Client="30"
"Client":30, ActiveClient="20"
"ActiveClient":20, Origin="12"
"Origin":12, ActiveOrigin="7" />
"ActiveOrigin":7
},
Client
전체 HTTP 클라이언트 세션수ActiveClient
전체 HTTP 클라이언트 중 전송 중인 세션수Origin
전체 원본서버 세션수ActiveOrigin
전체 원본서버 세션수 중 전송 중인 세션수
DIMS 통계¶
DIMS의 성능지표를 제공한다.
"Dims": <Dims
{ Requests="30"
"Requests": 30, Converted="29"
"Converted": 29, Failed="1"
"Failed": 1, AvgSrcSize="1457969"
"AvgSrcSize": 1457969, AvgDestSize="598831"
"AvgDestSize": 598831, AvgTime="34" />
"AvgTime": 34
},
Requests
변환요청 횟수Converted
변환성공 횟수Failed
변환실패 횟수AvgSrcSize (단위: Bytes)
원본 이미지의 평균 크기AvgDestSize (단위: Bytes)
변환된 이미지의 평균 크기AvgTime (단위: ms)
변환 소요시간
압축 통계¶
압축의 성능지표를 제공한다.
"Compression": <Compression
{ Requests="30"
"Requests": 30, Converted="29"
"Converted": 29, Failed="1"
"Failed": 1, AvgSrcSize="1457969"
"AvgSrcSize": 1457969, AvgDestSize="598831"
"AvgDestSize": 598831, AvgTime="34" />
"AvgTime": 34
},
Requests
압축요청 횟수Converted
압축성공 횟수Failed
압축실패 횟수AvgSrcSize (단위: Bytes)
원본 파일의 평균 크기AvgDestSize (단위: Bytes)
압축된 파일의 평균 크기AvgTime (단위: ms)
압축 소요시간
원본 통계¶
STON과 원본서버 사이에 발생하는 트래픽통계를 제공한다.
"OriginTraffic": <OriginTraffic>
{ <HttpReqCount Sum="600">2</HttpReqCount>
"HttpReqCountSum":0, <HttpReqHeaderSize>3238</HttpReqHeaderSize>
"HttpReqCount":0, <HttpReqBodySize>0</HttpReqBodySize>
"HttpReqHeaderSize":269, <HttpResHeaderSize>2020</HttpResHeaderSize>
"HttpReqBodySize":0, <HttpResBodySize>104894</HttpResBodySize>
"HttpResHeaderSize":169, <Response>
"HttpResBodySize":0, <ResTotal>
"Response": <Count Sum="8100">13</Count>
{ <Completed Sum="8100">12</Completed>
"ResTotal": <TimeRes>1553</TimeRes>
{ <TimeComplete>6630</TimeComplete>
"CountSum":0, </ResTotal>
"Count":1, <Res2xx>
"CompletedSum":0, <Count Sum="8100">1</Count>
"Completed":1, <Completed Sum="8100">1</Completed>
"TimeRes":3300, <TimeRes>3300</TimeRes>
"TimeComplete":3300 <TimeComplete>69300</TimeComplete>
}, </Res2xx>
"Res2xx": <Res3xx>
{ <Count Sum="8100">12</Count>
"CountSum":0, <Completed Sum="8100">11</Completed>
"Count":0, <TimeRes>1408</TimeRes>
"CompletedSum":0, <TimeComplete>1408</TimeComplete>
"Completed":0, </Res3xx>
"TimeRes":0, <Res4xx>
"TimeComplete":0 <Count Sum="8100">0</Count>
}, <Completed Sum="8100">0</Completed>
"Res3xx": <TimeRes>0</TimeRes>
{ <TimeComplete>0</TimeComplete>
"CountSum":0, </Res4xx>
"Count":1, <Res5xx>
"CompletedSum":0, <Count Sum="8100">0</Count>
"Completed":1, <Completed Sum="8100">0</Completed>
"TimeRes":3300, <TimeRes>0</TimeRes>
"TimeComplete":3300 <TimeComplete>0</TimeComplete>
}, </Res5xx>
"Res4xx": <ConnectTimeout Sum="8100">0</ConnectTimeout>
{ <ReceiveTimeout Sum="8100">0</ReceiveTimeout>
"CountSum":0, <Close Sum="8100">0</Close>
"Count":0, </Response>
"CompletedSum":0, <Connect>
"Completed":0, <Count>0</Count>
"TimeRes":0, <AvgDNSQueryTime>0</AvgDNSQueryTime>
"TimeComplete":0 <AvgConnTime>0</AvgConnTime>
}, </Connect>
"Res5xx": </OriginTraffic>
{
"CountSum":0,
"Count":0,
"CompletedSum":0,
"Completed":0,
"TimeRes":0,
"TimeComplete":0
},
"ConnectTimeoutSum":0,
"ConnectTimeout":0,
"ReceiveTimeoutSum":0,
"ReceiveTimeout":0,
"CloseSum":0,
"Close":0
},
"Connect":
{
"Count":0,
"AvgDNSQueryTime":0,
"AvgConnTime":0
}
},
HttpReqCount
원본서버로 보낸 HTTP 요청 횟수HttpReqHeaderSize (단위: Bytes)
원본서버로 보낸 HTTP 헤더 크기HttpReqBodySize (단위: Bytes)
원본서버로 보낸 HTTP Body 크기HttpResHeaderSize (단위: Bytes)
원본서버에서 받은 HTTP 헤더 크기HttpResBodySize (단위: Bytes)
원본서버에서 받은 HTTP Body 크기Response
원본서버에서 보낸 응답 (ResXXX)Count
응답횟수Completed
정상적으로 전송완료된 HTTP트랜잭션 횟수TimeRes
HTTP 응답시간TimeComplete
HTTP 트랜잭션 완료시간
Response
원본서버 연결에러ConnectTimeout
연결실패ReceiveTimeout
전송지연Close
전송 중 원본서버에서 먼저 소켓 종료
Connect
원본서버 접속통계Count
접속횟수AvgDNSQueryTime (단위: 0.01ms)
평균 DNS쿼리 시간AvgConnTime (단위: 0.01ms)
평균 접속시간 (TCP SYN전송 ~ TCP SYN ACK수신)
주석
5분 통계에서만 제공되는 항목.
HttpReqCountSum
HTTP요청의 총 회수CountSum
HTTP응답의 총 회수CompletedSum
완료된 HTTP 트랜잭션의 총 회수ConnectTimeoutSum
원본서버 접속실패 총 회수ReceiveTimeoutSum
원본서버 전송지연 총 회수CloseSum
원본서버에서 먼저 연결을 종료한 총 회수
포트바이패스 통계¶
<PortBypass>
를 통해 발생한 트래픽통계를 제공한다.
"PortBypass": <PortBypass SrcPort="1935" DestPost="1935">
[ <Session>0</Session>
{ <Hit Established="0"
"SrcPort":1935, "DestPort":1935, "Session":0, ClientClosed="0"
"Hit": OriginClosed="0"
{ OriginCT="0" />
"Established":0, "ClientClosed":0, <ClientTraffic In="0" Out="0"/>
"OriginClosed":0, "OriginCT":0 <OriginTraffic In="0" Out="0"/>
}, </PortBypass>
"ClientTraffic": { "In":0, "Out":0 }, <PortBypass SrcPort="1936" DestPost="1936">
"OriginTraffic": { "In":0, "Out":0 } <Session>17</Session>
}, ...
{ </PortBypass>
"SrcPort":1936, "DestPort":1936, "Session":17,
...
}
],
SrcPort/DestPort
바이패스 하는 STON포트/원본서버 포트Session
현재 연결된 세션 수Hit
바이패스 접속 통계Established
성립된 연결 개수ClientClosed
클라이언트가 연결 종료한 횟수OriginClosed
원본서버에서 연결 종료한 횟수OriginCT
원본서버 접속실패 횟수
ClientTraffic (단위: Bytes)
클라이언트 트래픽 (In=Inbound, Out=Outbound)OriginTraffic (단위: Bytes)
원본서버 트래픽 (In=Inbound, Out=Outbound)
클라이언트 통계¶
클라이언트 트래픽은 디렉토리별 통계설정 여부에 의해 “Traffic”이 멀티로 표현된다. 디렉토리별 통계를 설정하지 않았다면 모든 트래픽은 루트(/)로 집계된다. 디렉토리 통계가 설정되어 있다면 루트(/)와 트래픽이 발생한 디렉토리만 제공된다.
"ClientTraffic": <ClientTraffics Depth="0" Accum="OFF" HttpsTraffic="OFF">
{ <TrafficCount>1</TrafficCount>
"Depth":0, <Traffic RequestHitRatio="0">
"Accum":"OFF", <Path>/</Path>
"HttpsTraffic":"OFF", <HttpReqCount Sum="0">0</HttpReqCount>
"TrafficCount":1, <HttpReqHeaderSize>4113</HttpReqHeaderSize>
"Traffic": <HttpReqBodySize>0</HttpReqBodySize>
[ <HttpResHeaderSize>3066</HttpResHeaderSize>
{ <HttpResBodySize>892871</HttpResBodySize>
"RequestHitRatio" : 9984, <Response>
"Path":"/", <ResTotal>
"HttpReqCountSum":0, <Count Sum="0">18</Count>
"HttpReqCount":100, <Completed Sum="0">18</Completed>
"HttpReqHeaderSize":13968, <TimeRes>666</TimeRes>
"HttpReqBodySize":0, <TimeComplete>4377</TimeComplete>
"HttpResHeaderSize":5654, </ResTotal>
"HttpResBodySize":104744, <Res2xx>
"Response": <Count Sum="0">10</Count>
{ <Completed Sum="0">10</Completed>
"ResTotal": <TimeRes>1200</TimeRes>
{ <TimeComplete>7870</TimeComplete>
"CountSum":0, </Res2xx>
"Count":52, <Res3xx>
"CompletedSum":0, <Count Sum="0">8</Count>
"Completed":52, <Completed Sum="0">8</Completed>
"TimeRes":94, <TimeRes>0</TimeRes>
"TimeComplete":107 <TimeComplete>12</TimeComplete>
}, </Res3xx>
"Res2xx": <Res4xx>
{ <Count Sum="0">0</Count>
"CountSum":0, <Completed Sum="0">0</Completed>
"Count":1, <TimeRes>0</TimeRes>
"CompletedSum":0, <TimeComplete>0</TimeComplete>
"Completed":1, </Res4xx>
"TimeRes":4700, <Res5xx>
"TimeComplete":4800 <Count Sum="0">0</Count>
}, <Completed Sum="0">0</Completed>
"Res3xx": <TimeRes>0</TimeRes>
{ <TimeComplete>0</TimeComplete>
"CountSum":0, </Res5xx>
"Count":51, </Response>
"CompletedSum":0, <SSL RecvSize="0" SendSize="0"/>
"Completed":51, <RequestHit
"TimeRes":3, TCP_NONE="0"
"TimeComplete":15 TCP_HIT="0"
}, TCP_IMS_HIT="0"
"Res4xx": TCP_REFRESH_HIT="0"
{ TCP_REF_FAIL_HIT="0"
"CountSum":0, TCP_NEGATIVE_HIT="0"
"Count":0, TCP_REDIRECT_HIT="0"
"CompletedSum":0, TCP_MISS="0"
"Completed":0, TCP_REFRESH_MISS="0"
"TimeRes":0, TCP_CLIENT_REFRESH_MISS="0"
"TimeComplete":0 TCP_DENIED="0"
}, TCP_ERROR="0"/>
"Res5xx": <RequestHitSum
{ TCP_NONE="0"
"CountSum":0, TCP_HIT="0"
"Count":0, TCP_IMS_HIT="0"
"CompletedSum":0, TCP_REFRESH_HIT="0"
"Completed":0, TCP_REF_FAIL_HIT="0"
"TimeRes":0, TCP_NEGATIVE_HIT="0"
"TimeComplete":0 TCP_REDIRECT_HIT="0"
} TCP_MISS="0"
}, TCP_REFRESH_MISS="0"
"SSL": TCP_CLIENT_REFRESH_MISS="0"
{ TCP_DENIED="0"
"RecvSize":0, TCP_ERROR="0"/>
"SendSize":0 </Traffic>
}, <FileSystem>
"RequestHit": <GetAttr
{ TimeRes="0"
"TCP_NONE":0, FileCount="0"
"TCP_HIT":0, DirCount="0"
"TCP_IMS_HIT":0, FailCount="0">0</GetAttr>
"TCP_REFRESH_HIT":0, <Open TimeRes="0">0</Open>
"TCP_REF_FAIL_HIT":0, <Read
"TCP_NEGATIVE_HIT":0, TimeRes="0"
"TCP_REDIRECT_HIT":0, BufferSize="0"
"TCP_MISS":0, BufferFilled="0">0</Read>
"TCP_REFRESH_MISS":0, <RequestHit
"TCP_CLIENT_REFRESH_MISS":0, TCP_NONE="0"
"TCP_DENIED":0, TCP_HIT="0"
"TCP_ERROR":0 TCP_IMS_HIT="0"
}, TCP_REFRESH_HIT="0"
"RequestHitSum": TCP_REF_FAIL_HIT="0"
{ TCP_NEGATIVE_HIT="0"
"TCP_NONE":0, TCP_REDIRECT_HIT="0"
"TCP_HIT":0, TCP_MISS="0"
"TCP_IMS_HIT":0, TCP_REFRESH_MISS="0"
"TCP_REFRESH_HIT":0, TCP_CLIENT_REFRESH_MISS="0"
"TCP_REF_FAIL_HIT":0, TCP_DENIED="0"
"TCP_NEGATIVE_HIT":0, TCP_ERROR="0"/>
"TCP_REDIRECT_HIT":0, <RequestHitSum
"TCP_MISS":0, TCP_NONE="0"
"TCP_REFRESH_MISS":0, TCP_HIT="0"
"TCP_CLIENT_REFRESH_MISS":0, TCP_IMS_HIT="0"
"TCP_DENIED":0, TCP_REFRESH_HIT="0"
"TCP_ERROR":0 TCP_REF_FAIL_HIT="0"
}, TCP_NEGATIVE_HIT="0"
"FileSystem": TCP_REDIRECT_HIT="0"
{ TCP_MISS="0"
"GetAttr" : TCP_REFRESH_MISS="0"
{ TCP_CLIENT_REFRESH_MISS="0"
"TimeRes" : 0, TCP_DENIED="0"
"FileCount" : 0, TCP_ERROR="0"/>
"DirCount" : 0, </FileSystem>
"FailCount" : 0, </ClientTraffics>
"TotalCount" : 0
},
"Open" :
{
"TimeRes" : 0,
"Count" : 0
},
"Read" :
{
"TimeRes" : 0,
"BufferSize" : 0,
"BufferFilled" : 0,
"Count" : 0
},
"RequestHit":
{
"TCP_NONE":0,
"TCP_HIT":0,
"TCP_IMS_HIT":0,
"TCP_REFRESH_HIT":0,
"TCP_REF_FAIL_HIT":0,
"TCP_NEGATIVE_HIT":0,
"TCP_REDIRECT_HIT":0,
"TCP_MISS":0,
"TCP_REFRESH_MISS":0,
"TCP_CLIENT_REFRESH_MISS":0,
"TCP_DENIED":0,
"TCP_ERROR":0
},
"RequestHitSum":
{
"TCP_NONE":0,
"TCP_HIT":0,
"TCP_IMS_HIT":0,
"TCP_REFRESH_HIT":0,
"TCP_REF_FAIL_HIT":0,
"TCP_NEGATIVE_HIT":0,
"TCP_REDIRECT_HIT":0,
"TCP_MISS":0,
"TCP_REFRESH_MISS":0,
"TCP_CLIENT_REFRESH_MISS":0,
"TCP_DENIED":0,
"TCP_ERROR":0
}
}
}
]
}
Depth
통계를 수집할 디렉토리 DepthAccum
디렉토리 통계가 설정된 경우 하위 디렉토리의 통계를 상위 디렉토리로 누적시키는 설정HttpsTraffic
HTTPS트래픽을 HTTP트래픽으로 중복하여 집계하는 설정TrafficCount
집계된 트래픽 카운트Traffic
디렉토리별 통계. 루트(/)는 항상 존재한다.Path
서비스 디렉토리HttpReqCount(단위: Bytes)
클라이언트가 보낸 HTTP 요청 개수HttpReqHeaderSize(단위: Bytes)
클라이언트가 보낸 HTTP 요청 헤더 크기HttpReqBodySize(단위: Bytes)
클라이언트가 보낸 HTTP 요청 Body 크기HttpResHeaderSize(단위: Bytes)
STON이 보낸 HTTP 응답 헤더 크기HttpResBodySize(단위: Bytes)
STON이 보낸 HTTP 응답 Body 크기Response
STON이 보낸 응답Count
응답횟수Completed
정상적으로 전송완료된 HTTP트랜잭션 횟수TimeRes
HTTP 응답시간TimeComplete
HTTP 트랜잭션 완료시간
SSL(단위: Bytes)
HTTPS 트래픽 (RecvSize=수신크기, SendSize=송신크기)RequestHit
캐싱 HIT결과FileSystem
FileSystem 접근GetAttr
getattr함수 호출회수와 응답시간. (FileCount: File응답, DirCount: Dir응답, FailCount: 실패응답)Open
open함수 호출회수와 응답시간Read
read함수 호출회수와 응답시간, 요청크기(BufferSize)와 응답크기(BufferFilled)RequestHit
(File I/O 접근) 캐싱 HIT결과
주석
5분 통계에서만 제공되는 항목.
HttpReqCountSum
HTTP요청의 총 회수CountSum
HTTP응답의 총 회수CompletedSum
완료된 HTTP 트랜잭션의 총 회수RequestHitSum
캐시 HIT 결과
View¶
View는 가상호스트들을 하나로 묶어 통계를 추출하는 방식이다. Database에서 여러 Table을 마치 하나인 것처럼 다루는 View에서 따온 개념이다. 구성은 다음과 같이 아주 간단하다.
# vhosts.xml
<Vhosts>
<Vhost> ... </Vhost>
<Vhost> ... </Vhost>
... (생략) ...
<View Name="SK">
<Vhost>...</Vhost>
<Vhost>...</Vhost>
</View>
<View Name="KT">
<Vhost>...</Vhost>
<Vhost>...</Vhost>
<Vhost>...</Vhost>
</View>
<View Name="LG">
<Vhost>...</Vhost>
<Vhost>...</Vhost>
</View>
</Vhosts>
존재하지 않는 가상호스트로 View를 구성해도 상관없다. View가 제공하는 통계는 다음과 같다.
- Realtime XML/JSON
- SNMP - cache(1.3.6.1.4.1.40001.1.4).10 ~ 12
이해를 돕기 위해 View가 필요한 예를 들어보자. 류헌진, 서장혼, 박지송은 각각 자신이 좋아하는 스포츠 커뮤니티 사이트를 운영하고 있다.
# vhosts.xml
<Vhosts>
<Vhost Name="baseball.com"> ... </Vhost>
<Vhost Name="basketball.com"> ... </Vhost>
<Vhost Name="football.com"> ... </Vhost>
</Vhosts>
평소 친분이 있던 셋은 의기투합하여 스포츠 종합 커뮤니티 서비스를 오픈하기로 결정했다. 도메인도 서비스를 모두 아우를 수 있는 sports.com으로 정했다. 개발/운영팀이 해결해야하는 미션은 다음과 같다.
- 통합 서비스는 sports.com으로 한다.
- 기존 사용자를 위해 기존 도메인과 서비스는 그대로 유지한다.
- 개발팀은 통합한다. 운영팀은 통합한다.
- 대문(첫 페이지)만 신규 개발한다. 링크를 통해 기존 서비스를 이용한다.
- 예산이 없다. 사람이 없다. 시간이 없다. 정신이 없다.
- 이미 모든 구매절차가 끝났다.
이 모든 요구사항을 처리하는 현실적인 방법으로 개발팀은 다음과 같이 1번째 디렉토리에 기존 도메인을 명시하는 규칙을 사용하기로 결정했다.
# 기존 서비스
http://baseball.com/standing/list.html
http://basketball.com/stats/2014/view.html
http://football.com/player/messi.php
# 통합 서비스
http://sports.com/baseball/standing/list.html
http://sports.com/basketball/stats/2014/view.html
http://sports.com/football/player/messi.php
URL 전처리를 사용하면 간단히 설정할 수 있다.
# vhosts.xml
<Vhosts>
<Vhost Name="baseball.com"> ... </Vhost>
<Vhost Name="basketball.com"> ... </Vhost>
<Vhost Name="football.com"> ... </Vhost>
<URLRewrite>
<Pattern>sports.com/(.*)/(.*)</Pattern>
<Replace>#1.com/#2</Replace>
</URLRewrite>
</Vhosts>
통합된 운영팀에서는 이제 각각의 서비스 뿐만 아니라 통합된 서비스(트래픽, 세션, 응답코드 등)에 대해서도 모니터링해야 한다. 대부분 SNMP에 익숙한 관리자들이며 통합된 지표를 얻기 위해 다음과 같이 View를 구성한다.

# vhosts.xml
<Vhosts>
<Vhost Name="baseball.com"> ... </Vhost>
<Vhost Name="basketball.com"> ... </Vhost>
<Vhost Name="football.com"> ... </Vhost>
<URLRewrite>
<Pattern>sports.com/(.*)/(.*)</Pattern>
<Replace>#1.com/#2</Replace>
</URLRewrite>
<View Name="sports.com">
<Vhost>baseball.com</Vhost>
<Vhost>basketball.com</Vhost>
<Vhost>football.com</Vhost>
</View>
</Vhosts>
이상의 예에서 알 수 있듯이 URL Rewrite와 View의 조합은 기존 사이트를 하나로 묶어 서비스할 때 효과적이다.
View 통계¶
가상호스트와 동일한 통계를 제공한다. 다음과 같이 태그 이름만 다르다.
"View": <View ...>
[ ...
{ ... }, </View>
{ ... }, <View> ... </View>
] <View> ... </View>
가상호스트 목록조회¶
가상호스트 목록을 조회한다.
http://127.0.0.1:10040/monitoring/vhostslist
결과는 JSON형식으로 제공된다.
{
"version": "2.0.0",
"method": "vhostslist",
"status": "OK",
"result": [ "www.example.com","www.winesoft.com", "site1.com" ]
}
캐싱정보¶
캐싱하고 있는 파일상태를 모니터링한다. 일반적으로 파일은 URL로 구분되지만 같은 URL에 다른 옵션(i.e. Accept-Encoding등)이 존재하는 경우 여러 개의 파일이 존재할 수 있다.
http://127.0.0.1:10040/monitoring/fileinfo?url=example.com/sample.dat
결과는 JSON형식으로 제공된다. 다음은 /sample.dat파일의 정보를 열람한 결과이다.
{
"version": "2.0.0",
"method": "fileinfo",
"status": "OK",
"result":
[
{
"URI": "/sample.dat",
"Accept-Encoding": "N",
"RefCount": 0,
"Disk-Index": 0,
"Size": 2100267,
"FID": 24267,
"LocalPath": "/cache1/example.com/000i/q3.bin",
"File-Opened ": "N",
"File-Updating": "-",
"Downloader-Count": "0",
"LastAccess": "[ 2012.09.03 14:29:50, -2 ]",
"UpdateTime": "[ 2012.09.03 13:53:43, -2169 ]",
"TTL-Left": "[ 2012.10.03 13:53:43, 2589831 ]",
"ResponseCode": 200,
"ContentType": "text/plain",
"LastModifiedTime": "[ 2010.11.22 20:31:47, -56224685 ]",
"ExpireTime": "[ 0, 0 ]",
"CacheControl": "not-specified",
"ETag": "502dd614:200c2b",
"CustomTTL": 0,
"NoMoreExist": "N",
"LocalFileExist": "Y",
"SmallFile": "N",
"State": "Cached",
"Deleted": "N",
"AddedSize": "Y",
"TransferEncoding": "N",
"Compression": "-",
"Purge": "N",
"Ignore-IMS ": "N",
"Redirect-Location ": "-",
"Content-Disposition ": "-",
"NoCache": "N"
}
]
}
URI
파일 URIAccept-Encoding
(“Y” or “N”) Accept-Encoding을 지원한다면 “Y”RefCount
파일참조 카운트Size
(Bytes) 파일크기Disk-Index
(0부터 시작) 저장된 디스크 인덱스FID
파일 IDLocalPath
로컬 경로File-Opened
(“Y” or “N”) 로컬파일을 열고 있다면 “Y”File-Updating
파일을 갱신 중이라면 갱신하는 객체의 포인터가 명시Downloader-Count
원본서버에서 이 파일을 다운로드 받는 현재 세션의 개수LastAccess
(마지막 접근시간, 마지막 접근시간-현재시간) [ 2012.09.03 14:29:50, -2 ]의 의미는 2012.09.03 14:29:50에 접근됐으며 현재로부터 2초 전에 접근됐다는 의미이다.UpdateTime
(갱신시간, 갱신시간-현재시간) 파일이 마지막으로 갱신된 시간. 304 Not Modified에도 시간은 갱신된다.TTL-Left
(만료시간, 만료시간-현재시간) 컨텐츠 만료 예정시간. TTL이 남았다면 양수로, 만료됐다면 음수로 표기된다.ResponseCode
원본서버 응답코드ContentType
MIME TypeLastModifiedTime
(Last Modified Time, Last Modified Time`` 현재시간) 원본서버가 보낸 Last Modified Time. 원본서버가 이 값을 보내지 않았다면 0으로 표시된다.ExpireTime
(Expire Time, Expire Time`` 현재시간) 원본서버가 보낸 Expire Time. 원본서버가 이 값을 보내지 않았다면 0으로 표시된다.CacheControl
(“no-cache” or “not-specified” or (정수)) 원본서버가 보낸 Cache-Contorl 값ETag
STON이 생성한 ETagCustomTTL
커스텀 TTL. 설정되어 있지 않다면 0이다.NoMoreExist
(“Y” or “N”) 파일을 파기예약되어 있다면 “Y”LocalFileExist
(“Y” or “N”) 로컬에 파일이 존재하면 “Y” (200 OK가 아닌 파일들은 항상 “Y”)SmallFile
(“Y” or “N”) 파일을 작은파일로 판단한다면 “Y” (개발적인 이유)State
(“Not Init” or “Cached” or “Error”) 파일 상태Deleted
(“Y” or “N”) 삭제되었다면 “Y” (개발적인 이유)AddedSize
(“Y” or “N”) 크기가 통계에 반영되었다면 “Y” (개발적인 이유)TransferEncoding
(“Y” or “N”) Transfer-Encoding을 지원한다면 “Y”Compression
압축방식Purge
(“Y” or “N”) Purge됐다면 “Y”Ignore-IMS
(“Y” or “N”) 갱신할 때 If-Modified-Since헤더를 보내지 않도록 설정되었다면 “Y”Redirect-Location
Location 헤더 값Content-Disposition
Content-Disposition 헤더 값NoCache
(“Y” or “N”) 원본서버에서 no-cache응답을 줬다면 “Y”
Log Trace¶
기록되는 로그를 실시간으로 받아본다. Access, Origin, Monitoing로그는 가상호스트(vhost)를 지정해야 한다.
http://127.0.0.1:10040/monitoring/logtrace/info
http://127.0.0.1:10040/monitoring/logtrace/deny
http://127.0.0.1:10040/monitoring/logtrace/sys
http://127.0.0.1:10040/monitoring/logtrace/originerror
http://127.0.0.1:10040/monitoring/logtrace/access?vhost=www.site1.com
http://127.0.0.1:10040/monitoring/logtrace/origin?vhost=www.site1.com
http://127.0.0.1:10040/monitoring/logtrace/monitoring?vhost=www.site1.com
11장. SNMP¶
이 장에서는 SNMP(Simple Network Management Protocol)에 대해 다룬다. 10장. 모니터링 & 통계 의 모든 수치는 SNMP로도 제공된다. 뿐만 아니라 더욱 세분화된 시간단위와 시스템 상태정보까지 제공한다. 가상호스트별로 실시간 통계와 최대 60분까지 “분” 단위의 평균 통계를 제공한다.
- 별도의 패키지가 필요없다.
- snmpd를 별도로 실행하지 않는다.
- SNMP v1과 v2c를 지원한다.
변수¶
설정이나 사용자의 의도에 의하여 변경될 수 있는 값을 [변수명]으로 명시한다.
예를 들어 디스크는 여러개가 존재할 수 있다.
이 경우 각 디스크를 가리키는 고유 번호가 필요하며 입력된 순서대로 1부터 할당된다.
이런 변수를 [diskIndex]
로 명시한다.
[diskIndex]
Storage에 설정된 디스크를 의미한다.
# server.xml - <Server><Cache> <Storage> <Disk>/cache1</Disk> <Disk>/cache2</Disk> <Disk>/cache3</Disk> </Storage>
위와 같이 3개의 디스크가 설정된 환경에서 /cache1의
[diskIndex]
는 1, /cache3의[diskIndex]
는 3을 가진다. 예를 들어 /cache1의 전체용량에 해당하는 OID는 system.diskInfo.diskInfoTotalSize.1 (1.3.6.1.4.1.40001.1.2.18.1.3.1이 된다. 마지막 .1은 첫번째 디스크를 의미한다.[vhostIndex]
가상호스트가 로딩될 때 자동으로 부여된다.
# vhosts.xml <Vhosts> <Vhost Status="Active" Name="kim.com"> ... </Vhost> <Vhost Status="Active" Name="lee.com"> ... </Vhost> <Vhost Status="Active" Name="park.com" StaticIndex="10300"> ... </Vhost> </Vhosts>
최초 위와 같이 3개의 가상호스트가 로딩되면 1부터 순차적으로
[vhostIndex]
가 부여된다. 이후 가상호스트는[vhostIndex]
를 기억하며, 가상호스트가 삭제되더라도[vhostIndex]
는 변하지 않는다. 가상호스트의 삭제와 추가가 동시에 발생할 경우 삭제가 먼저 동작하며, 신규 추가된 가상호스트는 비어있는[vhostIndex]
를 부여 받는다.[vhostIndex]
의 동작방식[diskMin]
,[vhostMin]
시간(분)을 의미한다. 5는 5분의 평균을 의미하며 60은 60분의 평균을 의미한다. 이 값은 1(분)부터 60(분)까지 범위를 가지며 0은 실시간(1초) 데이터를 의미한다.
SNMP에서는 동적으로 값이 바뀔 수 있는 항목에 대하여 Table구조를 사용한다.
예를 들어 “디스크 전체크기”는 디스크의 개수에 따라 제공하는 데이터 개수가
달라지기 때문에 Table구조를 사용하여 표현해야 한다.
STON은 모든 가상호스트에 대하여 “분”단위 통계를 제공한다.
그러므로 [vhostMin]
. [vhostIndex]
라는 다소 난해한 표현을 제공한다.
이 표현은 가상호스트별로 원하는 “분” 단위의 통계를 볼 수 있다는 장점을 가지고 있지만
변수가 2개이므로 Table구조로 표현하기 어렵다는 단점이 있다.
이런 문제를 극복하기 위하여 [vhostMin]
의 기본값을 설정하여
SNMPWalk가 동작할 수 있도록 한다.
활성화¶
전역설정(server.xml)을 통해 SNMP동작방식과 ACL을 설정한다.
# server.xml - <Server><Host>
<SNMP Port="161" Status="Inactive">
<Allow>192.168.5.1</Allow>
<Allow>192.168.6.0/24</Allow>
</SNMP>
<SNMP>
속성을 통해 SNMP의 동작방식을 설정한다.Port (기본: 161)
SNMP 서비스 포트Status (기본: Inactive)
SNMP를 활성화 하려면 이 값을Active
로 설정한다.
<Allow>
SNMP접근을 허가할 IP주소를 설정한다.IP지정, IP범위지정, 비트마스크, 서브넷 이상 네 가지 형식을 지원한다. 접속한 소켓이 허가된 IP가 아니면 응답을 주지 않는다.
가상호스트/View 변수¶
SNMP를 통해 제공되는 가상호스트/View 개수와 기본시간(분)을 설정한다.
# server.xml - <Server><Host>
<SNMP VHostCount=0, VHostMin=5 ViewCount=0, ViewMin=5 />
VHostCount (기본: 0)
0일 경우 존재하는 가상호스트까지만 응답을 한다. 0보다 큰 값일 경우 가상호스트 존재 유무에 상관없이 설정된 가상호스트까지 응답한다.ViewCount (기본: 0)
View에 적용. (VHostCount
와 동일)VHostMin (기본: 5분, 최대: 60분)
[vhostMin]
값을 설정한다. 0~60까지의 값을 가진다. 0일 경우 실시간 데이터를 제공하하며 1~60사이인 경우 해당 분만큼의 평균값을 제공한다.ViewMin (기본: 0)
View에 적용. (VHostMin
와 동일)
예를 들어 3개의 가상호스트가 설정되어 있는 환경에서 SNMPWalk의 동작방식이 달라진다.
VHostCount=0인 경우
SNMPv2-SMI::enterprises.40001.1.4.2.1.2.1 = STRING: "web.winesoft.co.kr" SNMPv2-SMI::enterprises.40001.1.4.2.1.2.2 = STRING: "img.winesoft.co.kr" SNMPv2-SMI::enterprises.40001.1.4.2.1.2.3 = STRING: "vod.winesoft.co.kr"
VHostCount=5 경우
SNMPv2-SMI::enterprises.40001.1.4.2.1.2.1 = STRING: "web.winesoft.co.kr" SNMPv2-SMI::enterprises.40001.1.4.2.1.2.2 = STRING: "img.winesoft.co.kr" SNMPv2-SMI::enterprises.40001.1.4.2.1.2.3 = STRING: "vod.winesoft.co.kr" SNMPv2-SMI::enterprises.40001.1.4.2.1.2.4 = "" SNMPv2-SMI::enterprises.40001.1.4.2.1.2.5 = ""
기타 변수¶
기타 변수를 설정한다.
# server.xml - <Server><Host>
<SNMP GlobalMin="5" DiskMin="5" ConfCount="10" />
GlobalMin (기본: 5분, 최대: 60분)
[globalMin]
값을 설정한다.DiskMin (기본: 5분, 최대: 60분)
[diskMin]
값을 설정한다.ConfCount (기본: 10)
설정목록을 n개까지 열람한다. 1~100사이에서 지정 가능하다. 1은 현재 반영된 설정을 의미하며 2는 이전 설정을 의미한다. 100은 현재를 기준으로 99번 이전의 설정을 의미한다.
Community¶
Community를 설정하여 허가된 OID에만 접근/차단되도록 설정한다.
# server.xml - <Server><Host>
<SNMP UnregisteredCommunity="Allow">
<Community Name="example1" OID="Allow">
<OID>1.3.6.1.4.1.40001.1.4.1</OID>
<OID>1.3.6.1.4.1.40001.1.4.2</OID>
<OID>1.3.6.1.4.1.40001.1.4.4</OID>
</Community>
<Community Name="example2" OID="Deny">
<OID>1.3.6.1.4.1.40001.1.4.3.1.11.11.10.1-61</OID>
</Community>
</SNMP>
<SNMP>
의 UnregisteredCommunity
를 “Deny”로 설정하면 등록되지 않은 Community 요청은 차단한다.
<Community>
Community를 설정한다.Name
Community 이름.OID (기본: Allow)
하위<OID>
태그의 값을 설정한다. 속성 값이Allow
라면 하위<OID>
목록만 접근 가능하다. 반대로 속성 값이Deny
라면 하위 <OID>목록에는 접근이 불가능하다.
명시적인 OID(1.3.6.1.4.1.40001.1.4.4)와 범위OID(1.3.6.1.4.1.40001.1.4.3.1.11.11.10.1-61) 표현이 가능하다. OID를 허용/차단할 경우 하위 모든 OID에 대해 같은 규칙이 적용된다.
meta¶
OID = 1.3.6.1.4.1.40001.1.1
메타정보를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.1 | manufacture | String | “WineSOFT Inc.” |
.2 | software | String | “STON” |
.3 | version | String | 버전 |
.4 | hostname | String | 호스트 이름 |
.5 | state | String | “Healthy” 또는 “Inactive” 또는 “Emergency” |
.6 | uptime | Integer | 실행시간 (초) |
.7 | admin | String | <Admin> ... </Admin> |
.10 | Conf | OID | Conf 확장 |
meta.conf¶
OID = 1.3.6.1.4.1.40001.1.1.10
[confIndex]
는 <SNMP>
의 ConfCount
속성에서 설정한다.
[confIndex]
가 1인 경우는 항상 현재 적용된 설정 값을,
2인 경우는 이전 설정 값을 의미한다.
10 이라면 현재(1)로부터 9번째 이전의 설정을 의미한다.
OID | Name | Type | Description |
---|---|---|---|
.1. [confIndex] |
ID | Integer | 설정 ID |
.2. [confIndex] |
Time | Integer | 설정시간 (Unix 시간) |
.3. [confIndex] |
Type | Integer | 설정형태 (0 = Unknown, 1 = STON 시작, 2 = /conf/reload, 3 = /conf/upload, 4 = /conf/restore) |
.4. [confIndex] |
Size | Integer | 설정파일 크기 |
.5. [confIndex] |
Hash | String | 설정파일 Hash문자열 |
.6. [confIndex] |
Path | String | 설정파일 저장경로 |
.7. [confIndex] |
Ver | String | 설정할 때의 STON 버전 |
system¶
OID = 1.3.6.1.4.1.40001.1.2
STON이 동작하는 시스템 정보를 제공한다.
[sysMin]
변수는 0~60분까지의 값을 가지며 실시간 또는 원하는 시간만큼의 평균 값을 제공한다.
SNMPWalk에서 [sysMin]
은 0으로 설정되며 현재 정보를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.1. [sysMin] |
cpuTotal | Integer | 전체 CPU 사용률 (100%) |
.2. [sysMin] |
전체 CPU 사용률 (10000%) | ||
.3. [sysMin] |
cpuKernel | Integer | CPU(Kernel) 사용률 (100%) |
.4. [sysMin] |
CPU(Kernel) 사용률 (10000%) | ||
.5. [sysMin] |
cpuUser | Integer | CPU(User) 사용률 (100%) |
.6. [sysMin] |
CPU(User) 사용률 (10000%) | ||
.7. [sysMin] |
cpuIdle | Integer | CPU(Idle) 사용률 (100%) |
.8. [sysMin] |
CPU(Idle) 사용률 (10000%) | ||
.9 | memTotal | Integer | 시스템 전체 메모리 (KB) |
.10. [sysMin] |
memUse | Integer | 시스템 사용 메모리 (KB) |
.11. [sysMin] |
memFree | Integer | 시스템 여유 메모리 (KB) |
.12. [sysMin] |
memSTON | Integer | STON 사용 메모리 (KB) |
.13. [sysMin] |
memUseRatio | Integer | 시스템 메모리 사용률 (100%) |
.14. [sysMin] |
시스템 메모리 사용률 (10000%) | ||
.15. [sysMin] |
memSTONRatio | Integer | STON 메모리 사용률 (100%) |
.16. [sysMin] |
STON 메모리 사용률 (10000%) | ||
.17 | diskCount | Integer | disk개수 |
.18.1 | diskInfo | OID | diskInfo확장 |
.19.1 | diskPerf | OID | diskPerf확장 |
.20. [sysMin] |
cpuProcKernel | Integer | STON이 사용하는 CPU(Kernel) 사용률 (100%) |
.21. [sysMin] |
STON이 사용하는 CPU(Kernel) 사용률 (10000%) | ||
.22. [sysMin] |
cpuProcUser | Integer | STON이 사용하는 CPU(User) 사용률 (100%) |
.23. [sysMin] |
STON이 사용하는 CPU(User) 사용률 (10000%) | ||
.24. [sysMin] |
sysLoadAverage | Integer | Load Average 1분 평균 (0.01) |
.25. [sysMin] |
Load Average 5분 평균 (0.01) | ||
.26. [sysMin] |
Load Average 15분 평균 (0.01) | ||
.27. [sysMin] |
cpuNice | Integer | CPU(Nice) (100%) |
.28. [sysMin] |
CPU(Nice) (10000%) | ||
.29. [sysMin] |
cpuIOWait | Integer | CPU(IOWait) (100%) |
.30. [sysMin] |
CPU(IOWait) (10000%) | ||
.31. [sysMin] |
cpuIRQ | Integer | CPU(IRQ) (100%) |
.32. [sysMin] |
CPU(IRQ) (10000%) | ||
.33. [sysMin] |
cpuSoftIRQ | Integer | CPU(SoftIRQ) (100%) |
.34. [sysMin] |
CPU(SoftIRQ) (10000%) | ||
.35. [sysMin] |
cpuSteal | Integer | CPU(Steal) (100%) |
.36. [sysMin] |
CPU(Steal) | Integer | (10000%) |
.40. [sysMin] |
TCPSocket.Established. [globalMin] |
Integer | Established상태의 TCP 연결개수 |
.41. [sysMin] |
TCPSocket.Timewait. [globalMin] |
Integer | TIME_WAIT 상태의 TCP 연결개수 |
.42. [sysMin] |
TCPSocket.Orphan. [globalMin] |
Integer | 아직 file handle에 attach되지 않은 TCP 연결 |
.43. [sysMin] |
TCPSocket.Alloc. [globalMin] |
Integer | 할당된 TCP 연결 |
.44. [sysMin] |
TCPSocket.Mem. [globalMin] |
Integer | undocumented |
system.diskInfo¶
OID = 1.3.6.1.4.1.40001.1.2.18.1
디스크 정보를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.2. [diskIndex] |
diskInfoPath | String | 디스크 경로 |
.3. [diskIndex] |
diskInfoTotalSize | Integer | 디스크 전체용량 (MB) |
.4. [diskIndex] |
diskInfoUseSize | Integer | 디스크 사용량 (MB) |
.5. [diskIndex] |
diskInfoFreeSize | Integer | 디스크 사용 가능량 (MB) |
.6. [diskIndex] |
diskInfoUseRatio | Integer | 디스크 사용률 (100%) |
.7. [diskIndex] |
디스크 사용률 (10000%) | ||
.8. [diskIndex] |
diskInfoStatus | String | “Normal” 또는 “Invalid” 또는 “Unmounted” |
system.diskPerf¶
OID = 1.3.6.1.4.1.40001.1.2.19.1
디스크 성능상태를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.2. [diskMin] . [diskIndex] |
diskPerfReadCount | Integer | 읽기 성공 횟수 |
.3. [diskMin] . [diskIndex] |
diskPerfReadMergedCount | Integer | 읽기가 병합된 횟수 |
.4. [diskMin] . [diskIndex] |
diskPerfReadSectorsCount | Integer | 읽은 섹터 수 |
.5. [diskMin] . [diskIndex] |
diskPerfReadTime | Integer | 읽기 소요시간(ms) |
.6. [diskMin] . [diskIndex] |
diskPerfWriteCount | Integer | 쓰기 성공 횟수 |
.7. [diskMin] . [diskIndex] |
diskPerfWriteMergedCount | Integer | 쓰기가 병합된 횟수 |
.8. [diskMin] . [diskIndex] |
diskPerfWriteSectorsCount | Integer | 써진 섹터 수 |
.9. [diskMin] . [diskIndex] |
diskPerfWriteTime | Integer | 쓰기 소요시간(ms) |
.10. [diskMin] . [diskIndex] |
diskPerfIOProgressCount | Integer | 진행 중인 IO개수 |
.11. [diskMin] . [diskIndex] |
diskPerfIOTime | Integer | IO 소요시간(ms) |
.12. [diskMin] . [diskIndex] |
diskPerfIOTimeWeighted | Integer | IO 소요시간(ms, 가중치 적용) |
global¶
OID = 1.3.6.1.4.1.40001.1.3
STON의 모든 모듈이 공통적으로 사용하는 자원정보(소켓, 이벤트 등)를 제공한다.
ServerSocket
클라이언트 ~ STON구간. STON이 클라이언트의 요청을 처리할 용도로 사용하는 소켓
ClientSocket
STON ~ 원본서버구간. STON이 원본서버로 요청을 보내는 용도로 사용하는 소켓
OID | Name | Type | Description |
---|---|---|---|
.5 | EQ. [globalMin] |
Integer | STON Framework에서 아직 처리되지 않은 Event개수 |
.6 | RQ. [globalMin] |
Integer | 최근 서비스된 컨텐츠 참조 큐에 저장된 Event 개수 |
.7 | waitingFiles2Write. [globalMin] |
Integer | 쓰기대기 중인 파일개수 |
.10 | ServerSocket.Total. [globalMin] |
Integer | 전체 서버소켓 수 |
.11 | ServerSocket.Established. [globalMin] |
Integer | 연결된 상태의 서버소켓 수 |
.12 | ServerSocket.Accepted. [globalMin] |
Integer | 새롭게 연결된 서버소켓 수 |
.13 | ServerSocket.Closed. [globalMin] |
Integer | 연결이 종료된 서버소켓 수 |
.20 | ClientSocket.Total. [globalMin] |
Integer | 전체 클라이언트소켓 수 |
.21 | ClientSocket.Established. [globalMin] |
Integer | 연결된 상태의 클라이언트소켓 수 |
.22 | ClientSocket.Accepted. [globalMin] |
Integer | 새롭게 연결된 클라이언트소켓 수 |
.23 | ClientSocket.Closed. [globalMin] |
Integer | 연결이 종료된 클라이언트소켓 수 |
.30 | ServiceAccess.Allow. [globalMin] |
Integer | ServiceAccess에 의해 허가(Allow)된 소켓 수 |
.31 | ServiceAccess.Deny. [globalMin] |
Integer | ServiceAccess에 의해 거부(Deny)된 소켓 수 |
cache¶
OID = 1.3.6.1.4.1.40001.1.4
캐시 서비스의 통계는 가상호스트별로 상세하게 수집/제공된다.
OID | Name | Type | Description |
---|---|---|---|
.1 | host | OID | 호스트 (확장) |
.2 | vhostCount | Integer | 가상호스트 개수 |
.3.1 | vhost | OID | 가상호스트별 통계 |
.4 | vhostIndexMax | Integer | [vhostIndex] 최대 값. SNMPWalk는 이 수치를 기준으로 동작한다. |
.10 | viewCount | Integer | View 개수 |
.11.1 | view | OID | View별 통계 |
.12 | viewIndexMax | Integer | [viewIndex] 최대 값. SNMPWalk는 이 수치를 기준으로 동작한다. |
cache.host¶
OID = 1.3.6.1.4.1.40001.1.4.1
호스트(=모든 가상호스트)의 정보를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.2 | name | String | 호스트 이름 |
.3 | status | String | “Healthy” 또는 “Inactive” |
.4 | uptime | Integer | STON 실행시간 (초) |
.10 | contents | OID | 컨텐츠 정보 (확장) |
.11 | traffic | OID | 통계 (확장) |
cache.host.contents¶
OID = 1.3.6.1.4.1.40001.1.4.1.10
호스트(=모든 가상호스트)가 서비스하는 컨텐츠 통계를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.1 | memory | Integer | 메모리 캐싱 크기(KB) |
.2 | filesTotalCount | Integer | 서비스 중인 파일개수 |
.3 | filesTotalSize | Integer | 서비스 중인 전체 파일량(MB) |
.10 | filesCountU1KB | Integer | 1KB미만 파일개수 |
.11 | filesCountU2KB | Integer | 2KB미만 파일개수 |
.12 | filesCountU4KB | Integer | 4KB미만 파일개수 |
.13 | filesCountU8KB | Integer | 8KB미만 파일개수 |
.14 | filesCountU16KB | Integer | 16KB미만 파일개수 |
.15 | filesCountU32KB | Integer | 32KB미만 파일개수 |
.16 | filesCountU64KB | Integer | 64KB미만 파일개수 |
.17 | filesCountU128KB | Integer | 128KB미만 파일개수 |
.18 | filesCountU256KB | Integer | 256KB미만 파일개수 |
.19 | filesCountU512KB | Integer | 512KB미만 파일개수 |
.20 | filesCountU1MB | Integer | 1MB미만 파일개수 |
.21 | filesCountU2MB | Integer | 2MB미만 파일개수 |
.22 | filesCountU4MB | Integer | 4MB미만 파일개수 |
.23 | filesCountU8MB | Integer | 8MB미만 파일개수 |
.24 | filesCountU16MB | Integer | 16MB미만 파일개수 |
.25 | filesCountU32MB | Integer | 32MB미만 파일개수 |
.26 | filesCountU64MB | Integer | 64MB미만 파일개수 |
.27 | filesCountU128MB | Integer | 128MB미만 파일개수 |
.28 | filesCountU256MB | Integer | 256MB미만 파일개수 |
.29 | filesCountU512MB | Integer | 512MB미만 파일개수 |
.30 | filesCountU1GB | Integer | 1GB미만 파일개수 |
.31 | filesCountU2GB | Integer | 2GB미만 파일개수 |
.32 | filesCountU4GB | Integer | 4GB미만 파일개수 |
.33 | filesCountU8GB | Integer | 8GB미만 파일개수 |
.34 | filesCountU16GB | Integer | 16GB미만 파일개수 |
.35 | filesCountO16GB | Integer | 16GB이상 파일개수 |
cache.host.traffic¶
OID = 1.3.6.1.4.1.40001.1.4.1.11
호스트(=모든 가상호스트)의 캐시 서비스와 트래픽 통계를 제공한다. traffic의 모든 통계는 최대 60분까지의 평균으로 제공한다. min은 ‘분’을 의미하며 최대 60까지의 값을 가진다. min이 생략되거나 0이라면 실시간정보를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.1. [vhostMin] |
requestHitRatio | Integer | Request Hit Ratio(100%) |
.2. [vhostMin] |
Request Hit Ratio(10000%) | ||
.3. [vhostMin] |
bytesHitRatio | Integer | Bytes Hit Ratio(100%) |
.4. [vhostMin] |
Bytes Hit Ratio(10000%) | ||
.10 | origin | OID | 원본 트래픽 정보 (확장) |
.11 | client | OID | 클라이언트 트래픽 정보 (확장) |
cache.host.traffic.origin¶
OID = 1.3.6.1.4.1.40001.1.4.1.11.10
원본서버 트래픽 통계를 제공한다. 원본서버 트래픽은 HTTP트래픽과 Port바이패스 트래픽으로 구분한다.
OID | Name | Type | Description |
---|---|---|---|
.1. [vhostMin] |
inbound | Integer | 원본서버로부터 받는 평균 트래픽(Bytes) |
.2. [vhostMin] |
outbound | Integer | 원본서버로 보내는 평균 트래픽(Bytes) |
.3. [vhostMin] |
sessionAverage | Integer | 전체 원본서버 평균 세션수 |
.4. [vhostMin] |
activesessionAverage | Integer | 전체 원본서버 세션수 중 전송 중인 평균 세션수 |
.10 | http | OID | 원본서버 HTTP 트래픽 정보 |
.10.1. [vhostMin] |
http.inbound | Integer | 원본서버로부터 받는 평균 HTTP 트래픽(Bytes) |
.10.2. [vhostMin] |
http.outbound | Integer | 원본서버로 보내는 평균 HTTP 트래픽(Bytes) |
.10.3. [vhostMin] |
http.sessionAverage | Integer | 원본서버 평균 HTTP세션 수 |
.10.4. [vhostMin] |
http.reqHeaderSize | Integer | 원본서버로 보내는 평균 HTTP Header 트래픽(Bytes) |
.10.5. [vhostMin] |
http.reqBodySize | Integer | 원본서버로 보내는 평균 HTTP Body 트래픽(Bytes) |
.10.6. [vhostMin] |
http.resHeaderSize | Integer | 원본서버로부터 받는 평균 HTTP Header트래픽(Bytes) |
.10.7. [vhostMin] |
http.resBodySize | Integer | 원본서버로부터 받는 평균 HTTP Body트래픽(Bytes) |
.10.8. [vhostMin] |
http.reqAverage | Integer | 원본서버로 보낸 평균 HTTP요청 개수 |
.10.9. [vhostMin] |
http.reqCount | Integer | 원본서버로 보낸 HTTP요청 개수 |
.10.10. [vhostMin] |
http.resTotalAverage | Integer | 원본서버가 보낸 전체 평균 HTTP응답 개수 |
.10.11. [vhostMin] |
http.resTotalCompleteAverage | Integer | 원본서버로부터 성공한 평균 HTTP트랜잭션 개수 |
.10.12. [vhostMin] |
http.resTotalTimeRes | Integer | 원본서버로부터 응답 헤더를 받을때까지 평균 소요시간(0.01ms) |
.10.13. [vhostMin] |
http.resTotalTimeComplete | Integer | 원본서버로부터 응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.14. [vhostMin] |
http.resTotalCount | Integer | 원본서버가 보낸 전체 HTTP응답 개수 |
.10.15. [vhostMin] |
http.resTotalCompleteCount | Integer | 원본서버로부터 성공한 HTTP트랜잭션 개수 |
.10.20. [vhostMin] |
http.res2xxAverage | Integer | 원본서버가 보낸 평균 2xx응답 개수 |
.10.21. [vhostMin] |
http.res2xxCompleteAverage | Integer | 원본서버로부터 성공한 평균 2xx 트랜잭션 개수 |
.10.22. [vhostMin] |
http.res2xxTimeRes | Integer | 원본서버로부터 2xx응답 헤더를 받을때까지 평균 소요시간(0.01ms) |
.10.23. [vhostMin] |
http.res2xxTimeComplete | Integer | 원본서버로부터 2xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.24. [vhostMin] |
http.res2xxCount | Integer | 원본서버가 보낸 2xx응답 개수 |
.10.25. [vhostMin] |
http.res2xxCompleteCount | Integer | 원본서버로부터 성공한 2xx 트랜잭션 개수 |
.10.30. [vhostMin] |
http.res3xxAverage | Integer | 원본서버가 보낸 평균 3xx응답 개수 |
.10.31. [vhostMin] |
http.res3xxCompleteAverage | Integer | 원본서버로부터 성공한 평균 3xx 트랜잭션 개수 |
.10.32. [vhostMin] |
http.res3xxTimeRes | Integer | 원본서버로부터 3xx응답 헤더를 받을때까지 평균 소요시간(0.01ms) |
.10.33. [vhostMin] |
http.res3xxTimeComplete | Integer | 원본서버로부터 3xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.34. [vhostMin] |
http.res3xxCount | Integer | 원본서버가 보낸 3xx응답 개수 |
.10.35. [vhostMin] |
http.res3xxCompleteCount | Integer | 원본서버로부터 성공한 3xx 트랜잭션 개수 |
.10.40. [vhostMin] |
http.res4xxAverage | Integer | 원본서버가 보낸 평균 4xx응답 개수 |
.10.41. [vhostMin] |
http.res4xxCompleteAverage | Integer | 원본서버로부터 성공한 평균 4xx 트랜잭션 개수 |
.10.42. [vhostMin] |
http.res4xxTimeRes | Integer | 원본서버로부터 4xx응답 헤더를 받을때까지 평균 소요시간(0.01ms) |
.10.43. [vhostMin] |
http.res4xxTimeComplete | Integer | 원본서버로부터 4xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.44. [vhostMin] |
http.res4xxCount | Integer | 원본서버가 보낸 4xx응답 개수 |
.10.45. [vhostMin] |
http.res4xxCompleteCount | Integer | 원본서버로부터 성공한 4xx 트랜잭션 개수 |
.10.50. [vhostMin] |
http.res5xxAverage | Integer | 원본서버가 보낸 평균 5xx응답 개수 |
.10.51. [vhostMin] |
http.res5xxCompleteAverage | Integer | 원본서버로부터 성공한 평균 5xx 트랜잭션 개수 |
.10.52. [vhostMin] |
http.res5xxTimeRes | Integer | 원본서버로부터 5xx응답 헤더를 받을때까지 평균 소요시간(0.01ms) |
.10.53. [vhostMin] |
http.res5xxTimeComplete | Integer | 원본서버로부터 5xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.54. [vhostMin] |
http.res5xxCount | Integer | 원본서버가 보낸 5xx응답 개수 |
.10.55. [vhostMin] |
http.res5xxCompleteCount | Integer | 원본서버로부터 성공한 5xx 트랜잭션 개수 |
.10.60. [vhostMin] |
http.connectTimeoutAverage | Integer | 평균 원본서버 접속실패 횟수 |
.10.61. [vhostMin] |
http.receiveTimeoutAverage | Integer | 평균 원본서버 전송실패 횟수 |
.10.62. [vhostMin] |
http.connectAverage | Integer | 평균 원본서버 접속성공 횟수 |
.10.63. [vhostMin] |
http.dnsQueryTime | Integer | 원본서버 접속 시 평균 DNS쿼리 소요시간 |
.10.64. [vhostMin] |
http.connectTime | Integer | 원본서버 평균 접속 소요시간(0.01ms) |
.10.65. [vhostMin] |
http.connectTimeoutCount | Integer | 원본서버 접속실패 횟수 |
.10.66. [vhostMin] |
http.receiveTimeoutCount | Integer | 원본서버 전송실패 횟수 |
.10.67. [vhostMin] |
http.connectCount | Integer | 원본서버 접속성공 횟수 |
.10.68. [vhostMin] |
http.closeAverage | Integer | 전송 중 원본서버에서 먼저 소켓을 종료한 평균 횟수 |
.10.69. [vhostMin] |
http.closeCount | Integer | 전송 중 원본서버에서 먼저 소켓을 종료한 횟수 |
.11 | portbypass | OID | Port바이패스 원본서버 트래픽 정보 |
.11.1. [vhostMin] |
portbypass.inbound | Integer | Port바이패스를 통해 원본서버로부터 받는 평균 트래픽(Bytes) |
.11.2. [vhostMin] |
portbypass.outbound | Integer | Port바이패스를 통해 원본서버로 보내는 평균 트래픽(Bytes) |
.11.3. [vhostMin] |
portbypass.sessionAverage | Integer | Port바이패스 중인 평균 원본서버 세션 수 |
.11.4. [vhostMin] |
portbypass.closedAverage | Integer | Port바이패스 중 원본서버가 연결을 종료한 평균 횟수 |
.11.5. [vhostMin] |
portbypass.connectTimeoutAverage | Integer | Port바이패스 원본서버 평균 접속실패 횟수 |
.11.6. [vhostMin] |
portbypass.closedCount | Integer | Port바이패스 중 원본서버가 연결을 종료한 횟수 |
.11.7. [vhostMin] |
portbypass.connectTimeoutCount | Integer | Port바이패스 원본서버 접속실패 횟수 |
cache.host.traffic.client¶
OID = 1.3.6.1.4.1.40001.1.4.1.11.11
클라이언트 트래픽 통계를 제공한다. 클라이언트 트래픽은 HTTP트래픽, SSL트래픽, Port바이패스 트래픽으로 구분된다. SNMP에서는 디렉토리별 통계를 제공하지 않는다. 설령 디렉토리 통계가 설정되어 있다고 하더라도 합산되어 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.1. [vhostMin] |
inbound | Integer | 클라이언트로부터 받는 평균 트래픽(Bytes) |
.2. [vhostMin] |
outbound | Integer | 클라이언트로 보내는 평균 트래픽(Bytes) |
.3. [vhostMin] |
sessionAverage | Integer | 전체 클라이언트 평균 세션수 |
.4. [vhostMin] |
activesessionAverage | Integer | 전체 클라이언트 중 전송 중인 평균 세션수 |
.10 | http | OID | 클라이언트 HTTP 트래픽 정보 |
.10.1. [vhostMin] |
http.inbound | Integer | 클라이언트로부터 받는 평균 HTTP 트래픽(Bytes) |
.10.2. [vhostMin] |
http.outbound | Integer | 클라이언트로 보내는 평균 HTTP 트래픽(Bytes) |
.10.3. [vhostMin] |
http.sessionAverage | Integer | 클라이언트 평균 HTTP세션 수 |
.10.4. [vhostMin] |
http.reqHeaderSize | Integer | 클라이언트로부터 받는 평균 HTTP Header 트래픽(Bytes) |
.10.5. [vhostMin] |
http.reqBodySize | Integer | 클라이언트로부터 받는 평균 HTTP Body 트래픽(Bytes) |
.10.6. [vhostMin] |
http.resHeaderSize | Integer | 클라이언트로 보내는 평균 HTTP Header트래픽(Bytes) |
.10.7. [vhostMin] |
http.resBodySize | Integer | 클라이언트로 보내는 평균 HTTP Body트래픽(Bytes) |
.10.8. [vhostMin] |
http.reqAverage | Integer | 클라이언트로부터 받은 평균 HTTP요청 개수 |
.10.9. [vhostMin] |
http.reqCount | Integer | 클라이언트로부터 받은 HTTP요청 개수 |
.10.10. [vhostMin] |
http.resTotalAverage | Integer | 클라이언트로 보낸 평균 전체응답 개수 |
.10.11. [vhostMin] |
http.resTotalCompleteAverage | Integer | 클라이언트가 완료한 평균 HTTP 트랜잭션 개수 |
.10.12. [vhostMin] |
http.resTotalTimeRes | Integer | 클라이언트 응답 평균 소요시간(0.01ms) |
.10.13. [vhostMin] |
http.resTotalTimeComplete | Integer | 클라이언트 HTTP Transaction 평균 완료시간(0.01ms) |
.10.14. [vhostMin] |
http.resTotalCount | Integer | 클라이언트로 보낸 전체응답 개수 |
.10.15. [vhostMin] |
http.resTotalCompleteCount | Integer | 클라이언트가 완료한 HTTP 트랜잭션 개수 |
.10.20. [vhostMin] |
http.res2xxAverage | Integer | 클라이언트로 보낸 평균 2xx응답 개수 |
.10.21. [vhostMin] |
http.res2xxCompleteAverage | Integer | 클라이언트가 완료한 평균 2xx트랜잭션 개수 |
.10.22. [vhostMin] |
http.res2xxTimeRes | Integer | 클라이언트 2xx응답 평균 소요시간(0.01ms) |
.10.23. [vhostMin] |
http.res2xxTimeComplete | Integer | 클라이언트 2xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.24. [vhostMin] |
http.res2xxCount | Integer | 클라이언트로 보낸 2xx응답 개수 |
.10.25. [vhostMin] |
http.res2xxCompleteCount | Integer | 클라이언트가 완료한 2xx트랜잭션 개수 |
.10.30. [vhostMin] |
http.res3xxAverage | Integer | 클라이언트로 보낸 평균 3xx응답 개수 |
.10.31. [vhostMin] |
http.res3xxCompleteAverage | Integer | 클라이언트가 완료한 평균 3xx트랜잭션 개수 |
.10.32. [vhostMin] |
http.res3xxTimeRes | Integer | 클라이언트 3xx응답 평균 소요시간(0.01ms) |
.10.33. [vhostMin] |
http.res3xxTimeComplete | Integer | 클라이언트 3xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.34. [vhostMin] |
http.res3xxCount | Integer | 클라이언트로 보낸 3xx응답 개수 |
.10.35. [vhostMin] |
http.res3xxCompleteCount | Integer | 클라이언트가 완료한 3xx트랜잭션 개수 |
.10.40. [vhostMin] |
http.res4xxAverage | Integer | 클라이언트로 보낸 평균 4xx응답 개수 |
.10.41. [vhostMin] |
http.res4xxCompleteAverage | Integer | 클라이언트가 완료한 평균 4xx트랜잭션 개수 |
.10.42. [vhostMin] |
http.res4xxTimeRes | Integer | 클라이언트 4xx응답 평균 소요시간(0.01ms) |
.10.43. [vhostMin] |
http.res4xxTimeComplete | Integer | 클라이언트 4xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.44. [vhostMin] |
http.res4xxCount | Integer | 클라이언트로 보낸 4xx응답 개수 |
.10.45. [vhostMin] |
http.res4xxCompleteCount | Integer | 클라이언트가 완료한 4xx트랜잭션 개수 |
.10.50. [vhostMin] |
http.res5xxAverage | Integer | 클라이언트로 보낸 평균 5xx응답 개수 |
.10.51. [vhostMin] |
http.res5xxCompleteAverage | Integer | 클라이언트가 완료한 평균 5xx트랜잭션 개수 |
.10.52. [vhostMin] |
http.res5xxTimeRes | Integer | 클라이언트 5xx응답 평균 소요시간(0.01ms) |
.10.53. [vhostMin] |
http.res5xxTimeComplete | Integer | 클라이언트 5xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.54. [vhostMin] |
http.res5xxCount | Integer | 클라이언트로 보낸 5xx응답 개수 |
.10.55. [vhostMin] |
http.res5xxCompleteCount | Integer | 클라이언트가 완료한 5xx트랜잭션 개수 |
.10.60. [vhostMin] |
http.reqDeniedAverage | Integer | 차단된 요청 평균 |
.10.61. [vhostMin] |
http.reqDeniedCount | Integer | 차단된 요청 개수 |
.11 | portbypass | OID | Port바이패스 클라이언트 트래픽 정보 |
.11.1. [vhostMin] |
portbypass.inbound | Integer | Port바이패스를 통해 클라이언트로부터 받는 평균 트래픽(Bytes) |
.11.2. [vhostMin] |
portbypass.outbound | Integer | Port바이패스를 통해 클라이언트로 보내는 평균 트래픽(Bytes) |
.11.3. [vhostMin] |
portbypass.sessionAverage | Integer | Port바이패스 중인 클라이언트 평균 세션 수 |
.11.4. [vhostMin] |
portbypass.closedAverage | Integer | Port바이패스 중 클라이언트가 연결을 종료한 평균 횟수 |
.11.5. [vhostMin] |
portbypass.closedCount | Integer | Port바이패스 중 클라이언트가 연결을 종료한 횟수 |
.12 | ssl | OID | SSL 클라이언트 트래픽 정보 |
.12.2. [vhostMin] |
ssl.inbound | Integer | SSL을 통해 클라이언트로부터 받는 평균 트래픽(Bytes) |
.12.3. [vhostMin] |
ssl.outbound | Integer | SSL을 통해 클라이언트로 보내는 평균 트래픽(Bytes) |
.13 | requestHitAverage | OID | 평균 캐시 HIT결과 |
.13.1. [vhostMin] |
requestHitAverage.TCP_HIT | Integer | TCP_HIT |
.13.2. [vhostMin] |
requestHitAverage.TCP_IMS_HIT | Integer | TCP_IMS_HIT |
.13.3. [vhostMin] |
requestHitAverage.TCP_REFRESH_HIT | Integer | TCP_REFRESH_HIT |
.13.4. [vhostMin] |
requestHitAverage.TCP_REF_FAIL_HIT | Integer | TCP_REF_FAIL_HIT |
.13.5. [vhostMin] |
requestHitAverage.TCP_NEGATIVE_HIT | Integer | TCP_NEGATIVE_HIT |
.13.6. [vhostMin] |
requestHitAverage.TCP_MISS | Integer | TCP_MISS |
.13.7. [vhostMin] |
requestHitAverage.TCP_REFRESH_MISS | Integer | TCP_REFRESH_MISS |
.13.8. [vhostMin] |
requestHitAverage.TCP_CLIENT_REFRESH_MISS | Integer | TCP_CLIENT_REFRESH_MISS |
.13.9. [vhostMin] |
requestHitAverage.TCP_DENIED | Integer | TCP_DENIED |
.13.10. [vhostMin] |
requestHitAverage.TCP_ERROR | Integer | TCP_ERROR |
.13.11. [vhostMin] |
requestHitAverage.TCP_REDIRECT_HIT | Integer | TCP_REDIRECT_HIT |
.14 | requestHitCount | OID | 캐시 HIT결과 개수 |
.14.1. [vhostMin] |
requestHitCount.TCP_HIT | Integer | TCP_HIT |
.14.2. [vhostMin] |
requestHitCount.TCP_IMS_HIT | Integer | TCP_IMS_HIT |
.14.3. [vhostMin] |
requestHitCount.TCP_REFRESH_HIT | Integer | TCP_REFRESH_HIT |
.14.4. [vhostMin] |
requestHitCount.TCP_REF_FAIL_HIT | Integer | TCP_REF_FAIL_HIT |
.14.5. [vhostMin] |
requestHitCount.TCP_NEGATIVE_HIT | Integer | TCP_NEGATIVE_HIT |
.14.6. [vhostMin] |
requestHitCount.TCP_MISS | Integer | TCP_MISS |
.14.7. [vhostMin] |
requestHitCount.TCP_REFRESH_MISS | Integer | TCP_REFRESH_MISS |
.14.8. [vhostMin] |
requestHitCount.TCP_CLIENT_REFRESH_MISS | Integer | TCP_CLIENT_REFRESH_MISS |
.14.9. [vhostMin] |
requestHitCount.TCP_DENIED | Integer | TCP_DENIED |
.14.10. [vhostMin] |
requestHitCount.TCP_ERROR | Integer | TCP_ERROR |
.14.11. [vhostMin] |
requestHitCount.TCP_REDIRECT_HIT | Integer | TCP_REDIRECT_HIT |
cache.host.traffic.filesystem¶
OID = 1.3.6.1.4.1.40001.1.4.1.11.20
Host의 File I/O 통계를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.1. [vhostMin] |
requestHitRatio | Integer | Request Hit Ratio(100%) |
.2. [vhostMin] |
Request Hit Ratio(10000%) | ||
.3. [vhostMin] |
byteHitRatio | Integer | Byte Hit Ratio(100%) |
.4. [vhostMin] |
Byte Hit Ratio(10000%) | ||
.5. [vhostMin] |
outbound | Integer | File I/O로 보내는 평균 트래픽 (Bytes) |
.6. [vhostMin] |
session | Integer | File I/O를 진행 중인 평균 Thread개수 |
.7 | requestHitAverage | OID | 평균 캐시 HIT결과 |
.7.1. [vhostMin] |
requestHitAverage.TCP_HIT | Integer | TCP_HIT |
.7.2. [vhostMin] |
requestHitAverage.TCP_IMS_HIT | Integer | TCP_IMS_HIT |
.7.3. [vhostMin] |
requestHitAverage.TCP_REFRESH_HIT | Integer | TCP_REFRESH_HIT |
.7.4. [vhostMin] |
requestHitAverage.TCP_REF_FAIL_HIT | Integer | TCP_REF_FAIL_HIT |
.7.5. [vhostMin] |
requestHitAverage.TCP_NEGATIVE_HIT | Integer | TCP_NEGATIVE_HIT |
.7.6. [vhostMin] |
requestHitAverage.TCP_MISS | Integer | TCP_MISS |
.7.7. [vhostMin] |
requestHitAverage.TCP_REFRESH_MISS | Integer | TCP_REFRESH_MISS |
.7.8. [vhostMin] |
requestHitAverage.TCP_CLIENT_REFRESH_MISS | Integer | TCP_CLIENT_REFRESH_MISS |
.7.9. [vhostMin] |
requestHitAverage.TCP_DENIED | Integer | TCP_DENIED |
.7.10. [vhostMin] |
requestHitAverage.TCP_ERROR | Integer | TCP_ERROR |
.7.11. [vhostMin] |
requestHitAverage.TCP_REDIRECT_HIT | Integer | TCP_REDIRECT_HIT |
.8 | requestHitCount | OID | 캐시 HIT결과 개수 |
.8.1. [vhostMin] |
requestHitCount.TCP_HIT | Integer | TCP_HIT |
.8.2. [vhostMin] |
requestHitCount.TCP_IMS_HIT | Integer | TCP_IMS_HIT |
.8.3. [vhostMin] |
requestHitCount.TCP_REFRESH_HIT | Integer | TCP_REFRESH_HIT |
.8.4. [vhostMin] |
requestHitCount.TCP_REF_FAIL_HIT | Integer | TCP_REF_FAIL_HIT |
.8.5. [vhostMin] |
requestHitCount.TCP_NEGATIVE_HIT | Integer | TCP_NEGATIVE_HIT |
.8.6. [vhostMin] |
requestHitCount.TCP_MISS | Integer | TCP_MISS |
.8.7. [vhostMin] |
requestHitCount.TCP_REFRESH_MISS | Integer | TCP_REFRESH_MISS |
.8.8. [vhostMin] |
requestHitCount.TCP_CLIENT_REFRESH_MISS | Integer | TCP_CLIENT_REFRESH_MISS |
.8.9. [vhostMin] |
requestHitCount.TCP_DENIED | Integer | TCP_DENIED |
.8.10. [vhostMin] |
requestHitCount.TCP_ERROR | Integer | TCP_ERROR |
.8.11. [vhostMin] |
requestHitCount.TCP_REDIRECT_HIT | Integer | TCP_REDIRECT_HIT |
.10. [vhostMin] |
getattr.filecount | Integer | (getattr함수 호출) FILE로 응답한 회수 |
.11. [vhostMin] |
getattr.dircount | Integer | (getattr함수 호출) DIR로 응답한 회수 |
.12. [vhostMin] |
getattr.failcount | Integer | (getattr함수 호출) 실패로 응답한 회수 |
.13. [vhostMin] |
getattr.timeres | Integer | (getattr함수 호출) 반응시간 (0.01ms) |
.14. [vhostMin] |
open.count | Integer | open함수 호출 회수 |
.15. [vhostMin] |
open.timeres | Integer | open함수 반응시간 (0.01ms) |
.16. [vhostMin] |
read.count | Integer | read함수 호출 회수 |
.17. [vhostMin] |
read.timeres | Integer | read함수 반응시간 (0.01ms) |
.18. [vhostMin] |
read.buffersize | Integer | read함수에서 요청된 버퍼 크기 (Bytes) |
.19. [vhostMin] |
read.bufferfilled | Integer | read함수에서 요청된 버퍼에 채운 크기 (Bytes) |
cache.host.traffic.dims¶
OID = 1.3.6.1.4.1.40001.1.4.1.11.21
Host의 DIMS변환 통계를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.1. [vhostMin] |
requests | Integer | DIMS 변환요청 횟수 |
.2. [vhostMin] |
converted | Integer | 변환성공 횟수 |
.3. [vhostMin] |
failed | Integer | 변환실패 횟수 |
.4. [vhostMin] |
avgsrcsize | Integer | 원본 이미지의 평균 크기 (Bytes) |
.5. [vhostMin] |
avgdestsize | Integer | 변환된 이미지의 평균 크기 (Bytes) |
.6. [vhostMin] |
avgtime | Integer | 변환 소요시간 (ms) |
cache.host.traffic.compression¶
OID = 1.3.6.1.4.1.40001.1.4.1.11.22
Host의 압축 통계를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.1. [vhostMin] |
requests | Integer | 압축요청 횟수 |
.2. [vhostMin] |
converted | Integer | 압축성공 횟수 |
.3. [vhostMin] |
failed | Integer | 압축실패 횟수 |
.4. [vhostMin] |
avgsrcsize | Integer | 원본 파일의 평균 크기 (Bytes) |
.5. [vhostMin] |
avgdestsize | Integer | 압축된 파일의 평균 크기 (Bytes) |
.6. [vhostMin] |
avgtime | Integer | 압축 소요시간 (ms) |
cache.vhost¶
OID = 1.3.6.1.4.1.40001.1.4.3.1
가상호스트의 정보를 제공한다. [vhostIndex]
는 1부터 가상호스트 개수의 범위를 가진다.
OID | Name | Type | Description |
---|---|---|---|
.2. [vhostIndex] |
name | String | 가상호스트 이름 |
.3. [vhostIndex] |
status | String | “Healthy” 또는 “Inactive” 또는 “Emergency” |
.4. [vhostIndex] |
uptime | Integer | 가상호스트 실행시간 (초) |
.10 | contents | OID | 컨텐츠 정보 (확장) |
.11 | traffic | OID | 통계 (확장) |
cache.vhost.contents¶
OID = 1.3.6.1.4.1.40001.1.4.3.1.10
가상호스트가 서비스하는 컨텐츠 통계를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.1. [vhostIndex] |
memory | Integer | 메모리 캐싱 크기(KB) |
.2. [vhostIndex] |
filesTotalCount | Integer | 서비스 중인 파일개수 |
.3. [vhostIndex] |
filesTotalSize | Integer | 서비스 중인 전체 파일량(MB) |
.10. [vhostIndex] |
filesCountU1KB | Integer | 1KB미만 파일개수 |
.11. [vhostIndex] |
filesCountU2KB | Integer | 2KB미만 파일개수 |
.12. [vhostIndex] |
filesCountU4KB | Integer | 4KB미만 파일개수 |
.13. [vhostIndex] |
filesCountU8KB | Integer | 8KB미만 파일개수 |
.14. [vhostIndex] |
filesCountU16KB | Integer | 16KB미만 파일개수 |
.15. [vhostIndex] |
filesCountU32KB | Integer | 32KB미만 파일개수 |
.16. [vhostIndex] |
filesCountU64KB | Integer | 64KB미만 파일개수 |
.17. [vhostIndex] |
filesCountU128KB | Integer | 128KB미만 파일개수 |
.18. [vhostIndex] |
filesCountU256KB | Integer | 256KB미만 파일개수 |
.19. [vhostIndex] |
filesCountU512KB | Integer | 512KB미만 파일개수 |
.20. [vhostIndex] |
filesCountU1MB | Integer | 1MB미만 파일개수 |
.21. [vhostIndex] |
filesCountU2MB | Integer | 2MB미만 파일개수 |
.22. [vhostIndex] |
filesCountU4MB | Integer | 4MB미만 파일개수 |
.23. [vhostIndex] |
filesCountU8MB | Integer | 8MB미만 파일개수 |
.24. [vhostIndex] |
filesCountU16MB | Integer | 16MB미만 파일개수 |
.25. [vhostIndex] |
filesCountU32MB | Integer | 32MB미만 파일개수 |
.26. [vhostIndex] |
filesCountU64MB | Integer | 64MB미만 파일개수 |
.27. [vhostIndex] |
filesCountU128MB | Integer | 128MB미만 파일개수 |
.28. [vhostIndex] |
filesCountU256MB | Integer | 256MB미만 파일개수 |
.29. [vhostIndex] |
filesCountU512MB | Integer | 512MB미만 파일개수 |
.30. [vhostIndex] |
filesCountU1GB | Integer | 1GB미만 파일개수 |
.31. [vhostIndex] |
filesCountU2GB | Integer | 2GB미만 파일개수 |
.32. [vhostIndex] |
filesCountU4GB | Integer | 4GB미만 파일개수 |
.33. [vhostIndex] |
filesCountU8GB | Integer | 8GB미만 파일개수 |
.34. [vhostIndex] |
filesCountU16GB | Integer | 16GB미만 파일개수 |
.35. [vhostIndex] |
filesCountO16GB | Integer | 16GB이상 파일개수 |
cache.vhost.traffic¶
OID = 1.3.6.1.4.1.40001.1.4.3.1.11
가상호스트의 캐시 서비스와 트래픽 통계를 제공한다. traffic의 모든 통계는 최대 60분까지의 평균으로 제공된다. min은 ‘분’을 의미하며 최대 60까지의 값을 가진다. min이 생략되거나 0이라면 실시간정보를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.1. [vhostMin] . [vhostIndex] |
requestHitRatio | Integer | Request Hit Ratio(100%) |
.2. [vhostMin] . [vhostIndex] |
Request Hit Ratio(10000%) | ||
.3. [vhostMin] . [vhostIndex] |
bytesHitRatio | Integer | Bytes Hit Ratio(100%) |
.4. [vhostMin] . [vhostIndex] |
Bytes Hit Ratio(10000%) | ||
.10 | origin | OID | 원본 트래픽 정보 (확장) |
.11 | client | OID | 클라이언트 트래픽 정보 (확장) |
cache.vhost.traffic.origin¶
OID = 1.3.6.1.4.1.40001.1.4.3.1.11.10
원본서버 트래픽 통계를 제공한다. 원본서버 트래픽은 HTTP트래픽과 Port바이패스 트래픽으로 구분된다.
OID | Name | Type | Description |
---|---|---|---|
.1. [vhostMin] . [vhostIndex] |
inbound | Integer | 원본서버로부터 받는 평균 트래픽(Bytes) |
.2. [vhostMin] . [vhostIndex] |
outbound | Integer | 원본서버로 보내는 평균 트래픽(Bytes) |
.3. [vhostMin] . [vhostIndex] |
sessionAverage | Integer | 전체 원본서버 평균 세션수 |
.4. [vhostMin] . [vhostIndex] |
activesessionAverage | Integer | 전체 원본서버 세션수 중 전송 중인 평균 세션수 |
.10 | http | OID | 원본서버 HTTP 트래픽 정보 |
.10.1. [vhostMin] . [vhostIndex] |
http.inbound | Integer | 원본서버로부터 받는 평균 HTTP 트래픽(Bytes) |
.10.2. [vhostMin] . [vhostIndex] |
http.outbound | Integer | 원본서버로 보내는 평균 HTTP 트래픽(Bytes) |
.10.3. [vhostMin] . [vhostIndex] |
http.sessionAverage | Integer | 원본서버 평균 HTTP세션 수 |
.10.4. [vhostMin] . [vhostIndex] |
http.reqHeaderSize | Integer | 원본서버로 보내는 평균 HTTP Header 트래픽(Bytes) |
.10.5. [vhostMin] . [vhostIndex] |
http.reqBodySize | Integer | 원본서버로 보내는 평균 HTTP Body 트래픽(Bytes) |
.10.6. [vhostMin] . [vhostIndex] |
http.resHeaderSize | Integer | 원본서버로부터 받는 평균 HTTP Header트래픽(Bytes) |
.10.7. [vhostMin] . [vhostIndex] |
http.resBodySize | Integer | 원본서버로부터 받는 평균 HTTP Body트래픽(Bytes) |
.10.8. [vhostMin] . [vhostIndex] |
http.reqAverage | Integer | 원본서버로 보낸 평균 HTTP요청 개수 |
.10.9. [vhostMin] . [vhostIndex] |
http.reqCount | Integer | 원본서버로 보낸 HTTP요청 개수 |
.10.10. [vhostMin] . [vhostIndex] |
http.resTotalAverage | Integer | 원본서버가 보낸 전체 평균 HTTP응답 개수 |
.10.11. [vhostMin] . [vhostIndex] |
http.resTotalCompleteAverage | Integer | 원본서버로부터 성공한 평균 HTTP트랜잭션 개수 |
.10.12. [vhostMin] . [vhostIndex] |
http.resTotalTimeRes | Integer | 원본서버로부터 응답 헤더를 받을때까지 평균 소요시간(0.01ms) |
.10.13. [vhostMin] . [vhostIndex] |
http.resTotalTimeComplete | Integer | 원본서버로부터 응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.14. [vhostMin] . [vhostIndex] |
http.resTotalCount | Integer | 원본서버가 보낸 전체 HTTP응답 개수 |
.10.15. [vhostMin] . [vhostIndex] |
http.resTotalCompleteCount | Integer | 원본서버로부터 성공한 HTTP트랜잭션 개수 |
.10.20. [vhostMin] . [vhostIndex] |
http.res2xxAverage | Integer | 원본서버가 보낸 평균 2xx응답 개수 |
.10.21. [vhostMin] . [vhostIndex] |
http.res2xxCompleteAverage | Integer | 원본서버로부터 성공한 평균 2xx 트랜잭션 개수 |
.10.22. [vhostMin] . [vhostIndex] |
http.res2xxTimeRes | Integer | 원본서버로부터 2xx응답 헤더를 받을때까지 평균 소요시간(0.01ms) |
.10.23. [vhostMin] . [vhostIndex] |
http.res2xxTimeComplete | Integer | 원본서버로부터 2xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.24. [vhostMin] . [vhostIndex] |
http.res2xxCount | Integer | 원본서버가 보낸 2xx응답 개수 |
.10.25. [vhostMin] . [vhostIndex] |
http.res2xxCompleteCount | Integer | 원본서버로부터 성공한 2xx 트랜잭션 개수 |
.10.30. [vhostMin] . [vhostIndex] |
http.res3xxAverage | Integer | 원본서버가 보낸 평균 3xx응답 개수 |
.10.31. [vhostMin] . [vhostIndex] |
http.res3xxCompleteAverage | Integer | 원본서버로부터 성공한 평균 3xx 트랜잭션 개수 |
.10.32. [vhostMin] . [vhostIndex] |
http.res3xxTimeRes | Integer | 원본서버로부터 3xx응답 헤더를 받을때까지 평균 소요시간(0.01ms) |
.10.33. [vhostMin] . [vhostIndex] |
http.res3xxTimeComplete | Integer | 원본서버로부터 3xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.34. [vhostMin] . [vhostIndex] |
http.res3xxCount | Integer | 원본서버가 보낸 3xx응답 개수 |
.10.35. [vhostMin] . [vhostIndex] |
http.res3xxCompleteCount | Integer | 원본서버로부터 성공한 3xx 트랜잭션 개수 |
.10.40. [vhostMin] . [vhostIndex] |
http.res4xxAverage | Integer | 원본서버가 보낸 평균 4xx응답 개수 |
.10.41. [vhostMin] . [vhostIndex] |
http.res4xxCompleteAverage | Integer | 원본서버로부터 성공한 평균 4xx 트랜잭션 개수 |
.10.42. [vhostMin] . [vhostIndex] |
http.res4xxTimeRes | Integer | 원본서버로부터 4xx응답 헤더를 받을때까지 평균 소요시간(0.01ms) |
.10.43. [vhostMin] . [vhostIndex] |
http.res4xxTimeComplete | Integer | 원본서버로부터 4xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.44. [vhostMin] . [vhostIndex] |
http.res4xxCount | Integer | 원본서버가 보낸 4xx응답 개수 |
.10.45. [vhostMin] . [vhostIndex] |
http.res4xxCompleteCount | Integer | 원본서버로부터 성공한 4xx 트랜잭션 개수 |
.10.50. [vhostMin] . [vhostIndex] |
http.res5xxAverage | Integer | 원본서버가 보낸 평균 5xx응답 개수 |
.10.51. [vhostMin] . [vhostIndex] |
http.res5xxCompleteAverage | Integer | 원본서버로부터 성공한 평균 5xx 트랜잭션 개수 |
.10.52. [vhostMin] . [vhostIndex] |
http.res5xxTimeRes | Integer | 원본서버로부터 5xx응답 헤더를 받을때까지 평균 소요시간(0.01ms) |
.10.53. [vhostMin] . [vhostIndex] |
http.res5xxTimeComplete | Integer | 원본서버로부터 5xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.54. [vhostMin] . [vhostIndex] |
http.res5xxCount | Integer | 원본서버가 보낸 5xx응답 개수 |
.10.55. [vhostMin] . [vhostIndex] |
http.res5xxCompleteCount | Integer | 원본서버로부터 성공한 5xx 트랜잭션 개수 |
.10.60. [vhostMin] . [vhostIndex] |
http.connectTimeoutAverage | Integer | 평균 원본서버 접속실패 횟수 |
.10.61. [vhostMin] . [vhostIndex] |
http.receiveTimeoutAverage | Integer | 평균 원본서버 전송실패 횟수 |
.10.62. [vhostMin] . [vhostIndex] |
http.connectAverage | Integer | 평균 원본서버 접속성공 횟수 |
.10.63. [vhostMin] . [vhostIndex] |
http.dnsQueryTime | Integer | 원본서버 접속 시 평균 DNS쿼리 소요시간 |
.10.64. [vhostMin] . [vhostIndex] |
http.connectTime | Integer | 원본서버 평균 접속 소요시간(0.01ms) |
.10.65. [vhostMin] . [vhostIndex] |
http.connectTimeoutCount | Integer | 원본서버 접속실패 횟수 |
.10.66. [vhostMin] . [vhostIndex] |
http.receiveTimeoutCount | Integer | 원본서버 전송실패 횟수 |
.10.67. [vhostMin] . [vhostIndex] |
http.connectCount | Integer | 원본서버 접속성공 횟수 |
.10.68. [vhostMin] . [vhostIndex] |
http.closeAverage | Integer | 전송 중 원본서버에서 먼저 소켓을 종료한 평균 횟수 |
.10.69. [vhostMin] . [vhostIndex] |
http.closeCount | Integer | 전송 중 원본서버에서 먼저 소켓을 종료한 횟수 |
.11 | portbypass | OID | Port바이패스 원본서버 트래픽 정보 |
.11.1. [vhostMin] . [vhostIndex] |
portbypass.inbound | Integer | Port바이패스를 통해 원본서버로부터 받는 평균 트래픽(Bytes) |
.11.2. [vhostMin] . [vhostIndex] |
portbypass.outbound | Integer | Port바이패스를 통해 원본서버로 보내는 평균 트래픽(Bytes) |
.11.3. [vhostMin] . [vhostIndex] |
portbypass.sessionAverage | Integer | Port바이패스 중인 평균 원본서버 세션 수 |
.11.4. [vhostMin] . [vhostIndex] |
portbypass.closedAverage | Integer | Port바이패스 중 원본서버가 연결을 종료한 평균 횟수 |
.11.5. [vhostMin] . [vhostIndex] |
portbypass.connectTimeoutAverage | Integer | Port바이패스 원본서버 평균 접속실패 횟수 |
.11.6. [vhostMin] . [vhostIndex] |
portbypass.closedCount | Integer | Port바이패스 중 원본서버가 연결을 종료한 횟수 |
.11.7. [vhostMin] . [vhostIndex] |
portbypass.connectTimeoutCount | Integer | Port바이패스 원본서버 접속실패 횟수 |
cache.vhost.traffic.client¶
OID = 1.3.6.1.4.1.40001.1.4.3.1.11.11
클라이언트 트래픽 통계를 제공한다. 클라이언트 트래픽은 HTTP트래픽, SSL트래픽, Port바이패스 트래픽으로 구분된다. SNMP에서는 디렉토리별 통계를 제공하지 않는다. 설령 디렉토리 통계가 설정되어 있다고 하더라도 합산되어 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.1. [vhostMin] . [vhostIndex] |
inbound | Integer | 클라이언트로부터 받는 평균 트래픽(Bytes) |
.2. [vhostMin] . [vhostIndex] |
outbound | Integer | 클라이언트로 보내는 평균 트래픽(Bytes) |
.3. [vhostMin] . [vhostIndex] |
sessionAverage | Integer | 전체 클라이언트 평균 세션수 |
.4. [vhostMin] . [vhostIndex] |
activesessionAverage | Integer | 전체 클라이언트 중 전송 중인 평균 세션수 |
.10 | http | OID | 클라이언트 HTTP 트래픽 정보 |
.10.1. [vhostMin] . [vhostIndex] |
http.inbound | Integer | 클라이언트로부터 받는 평균 HTTP 트래픽(Bytes) |
.10.2. [vhostMin] . [vhostIndex] |
http.outbound | Integer | 클라이언트로 보내는 평균 HTTP 트래픽(Bytes) |
.10.3. [vhostMin] . [vhostIndex] |
http.sessionAverage | Integer | 클라이언트 평균 HTTP세션 수 |
.10.4. [vhostMin] . [vhostIndex] |
http.reqHeaderSize | Integer | 클라이언트로부터 받는 평균 HTTP Header 트래픽(Bytes) |
.10.5. [vhostMin] . [vhostIndex] |
http.reqBodySize | Integer | 클라이언트로부터 받는 평균 HTTP Body 트래픽(Bytes) |
.10.6. [vhostMin] . [vhostIndex] |
http.resHeaderSize | Integer | 클라이언트로 보내는 평균 HTTP Header트래픽(Bytes) |
.10.7. [vhostMin] . [vhostIndex] |
http.resBodySize | Integer | 클라이언트로 보내는 평균 HTTP Body트래픽(Bytes) |
.10.8. [vhostMin] . [vhostIndex] |
http.reqAverage | Integer | 클라이언트로부터 받은 평균 HTTP요청 개수 |
.10.9. [vhostMin] . [vhostIndex] |
http.reqCount | Integer | 클라이언트로부터 받은 HTTP요청 개수 |
.10.10. [vhostMin] . [vhostIndex] |
http.resTotalAverage | Integer | 클라이언트로 보낸 평균 전체응답 개수 |
.10.11. [vhostMin] . [vhostIndex] |
http.resTotalCompleteAverage | Integer | 클라이언트가 완료한 평균 HTTP 트랜잭션 개수 |
.10.12. [vhostMin] . [vhostIndex] |
http.resTotalTimeRes | Integer | 클라이언트 응답 평균 소요시간(0.01ms) |
.10.13. [vhostMin] . [vhostIndex] |
http.resTotalTimeComplete | Integer | 클라이언트 HTTP Transaction 평균 완료시간(0.01ms) |
.10.14. [vhostMin] . [vhostIndex] |
http.resTotalCount | Integer | 클라이언트로 보낸 전체응답 개수 |
.10.15. [vhostMin] . [vhostIndex] |
http.resTotalCompleteCount | Integer | 클라이언트가 완료한 HTTP 트랜잭션 개수 |
.10.20. [vhostMin] . [vhostIndex] |
http.res2xxAverage | Integer | 클라이언트로 보낸 평균 2xx응답 개수 |
.10.21. [vhostMin] . [vhostIndex] |
http.res2xxCompleteAverage | Integer | 클라이언트가 완료한 평균 2xx트랜잭션 개수 |
.10.22. [vhostMin] . [vhostIndex] |
http.res2xxTimeRes | Integer | 클라이언트 2xx응답 평균 소요시간(0.01ms) |
.10.23. [vhostMin] . [vhostIndex] |
http.res2xxTimeComplete | Integer | 클라이언트 2xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.24. [vhostMin] . [vhostIndex] |
http.res2xxCount | Integer | 클라이언트로 보낸 2xx응답 개수 |
.10.25. [vhostMin] . [vhostIndex] |
http.res2xxCompleteCount | Integer | 클라이언트가 완료한 2xx트랜잭션 개수 |
.10.30. [vhostMin] . [vhostIndex] |
http.res3xxAverage | Integer | 클라이언트로 보낸 평균 3xx응답 개수 |
.10.31. [vhostMin] . [vhostIndex] |
http.res3xxCompleteAverage | Integer | 클라이언트가 완료한 평균 3xx트랜잭션 개수 |
.10.32. [vhostMin] . [vhostIndex] |
http.res3xxTimeRes | Integer | 클라이언트 3xx응답 평균 소요시간(0.01ms) |
.10.33. [vhostMin] . [vhostIndex] |
http.res3xxTimeComplete | Integer | 클라이언트 3xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.34. [vhostMin] . [vhostIndex] |
http.res3xxCount | Integer | 클라이언트로 보낸 3xx응답 개수 |
.10.35. [vhostMin] . [vhostIndex] |
http.res3xxCompleteCount | Integer | 클라이언트가 완료한 3xx트랜잭션 개수 |
.10.40. [vhostMin] . [vhostIndex] |
http.res4xxAverage | Integer | 클라이언트로 보낸 평균 4xx응답 개수 |
.10.41. [vhostMin] . [vhostIndex] |
http.res4xxCompleteAverage | Integer | 클라이언트가 완료한 평균 4xx트랜잭션 개수 |
.10.42. [vhostMin] . [vhostIndex] |
http.res4xxTimeRes | Integer | 클라이언트 4xx응답 평균 소요시간(0.01ms) |
.10.43. [vhostMin] . [vhostIndex] |
http.res4xxTimeComplete | Integer | 클라이언트 4xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.44. [vhostMin] . [vhostIndex] |
http.res4xxCount | Integer | 클라이언트로 보낸 4xx응답 개수 |
.10.45. [vhostMin] . [vhostIndex] |
http.res4xxCompleteCount | Integer | 클라이언트가 완료한 4xx트랜잭션 개수 |
.10.50. [vhostMin] . [vhostIndex] |
http.res5xxAverage | Integer | 클라이언트로 보낸 평균 5xx응답 개수 |
.10.51. [vhostMin] . [vhostIndex] |
http.res5xxCompleteAverage | Integer | 클라이언트가 완료한 평균 5xx트랜잭션 개수 |
.10.52. [vhostMin] . [vhostIndex] |
http.res5xxTimeRes | Integer | 클라이언트 5xx응답 평균 소요시간(0.01ms) |
.10.53. [vhostMin] . [vhostIndex] |
http.res5xxTimeComplete | Integer | 클라이언트 5xx응답 HTTP Transaction 평균 완료시간(0.01ms) |
.10.54. [vhostMin] . [vhostIndex] |
http.res5xxCount | Integer | 클라이언트로 보낸 5xx응답 개수 |
.10.55. [vhostMin] . [vhostIndex] |
http.res5xxCompleteCount | Integer | 클라이언트가 완료한 5xx트랜잭션 개수 |
.10.60. [vhostMin] . [vhostIndex] |
http.reqDeniedAverage | Integer | 차단된 요청 평균 |
.10.61. [vhostMin] . [vhostIndex] |
http.reqDeniedCount | Integer | 차단된 요청 개수 |
.11 | portbypass | OID | Port바이패스 클라이언트 트래픽 정보 |
.11.1. [vhostMin] . [vhostIndex] |
portbypass.inbound | Integer | Port바이패스를 통해 클라이언트로부터 받는 평균 트래픽(Bytes) |
.11.2. [vhostMin] . [vhostIndex] |
portbypass.outbound | Integer | Port바이패스를 통해 클라이언트로 보내는 평균 트래픽(Bytes) |
.11.3. [vhostMin] . [vhostIndex] |
portbypass.sessionAverage | Integer | Port바이패스 중인 클라이언트 평균 세션 수 |
.11.4. [vhostMin] . [vhostIndex] |
portbypass.closedAverage | Integer | Port바이패스 중 클라이언트가 연결을 종료한 평균 횟수 |
.11.5. [vhostMin] . [vhostIndex] |
portbypass.closedCount | Integer | Port바이패스 중 클라이언트가 연결을 종료한 횟수 |
.12 | ssl | OID | SSL 클라이언트 트래픽 정보 |
.12.2. [vhostMin] . [vhostIndex] |
ssl.inbound | Integer | SSL을 통해 클라이언트로부터 받는 평균 트래픽(Bytes) |
.12.3. [vhostMin] . [vhostIndex] |
ssl.outbound | Integer | SSL을 통해 클라이언트로 보내는 평균 트래픽(Bytes) |
.13 | requestHitAverage | OID | 평균 캐시 HIT결과 |
.13.1. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_HIT | Integer | TCP_HIT |
.13.2. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_IMS_HIT | Integer | TCP_IMS_HIT |
.13.3. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_REFRESH_HIT | Integer | TCP_REFRESH_HIT |
.13.4. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_REF_FAIL_HIT | Integer | TCP_REF_FAIL_HIT |
.13.5. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_NEGATIVE_HIT | Integer | TCP_NEGATIVE_HIT |
.13.6. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_MISS | Integer | TCP_MISS |
.13.7. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_REFRESH_MISS | Integer | TCP_REFRESH_MISS |
.13.8. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_CLIENT_REFRESH_MISS | Integer | TCP_CLIENT_REFRESH_MISS |
.13.9. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_DENIED | Integer | TCP_DENIED |
.13.10. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_ERROR | Integer | TCP_ERROR |
.13.11. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_REDIRECT_HIT | Integer | TCP_REDIRECT_HIT |
.14 | requestHitCount | OID | 캐시 HIT결과 개수 |
.14.1. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_HIT | Integer | TCP_HIT |
.14.2. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_IMS_HIT | Integer | TCP_IMS_HIT |
.14.3. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_REFRESH_HIT | Integer | TCP_REFRESH_HIT |
.14.4. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_REF_FAIL_HIT | Integer | TCP_REF_FAIL_HIT |
.14.5. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_NEGATIVE_HIT | Integer | TCP_NEGATIVE_HIT |
.14.6. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_MISS | Integer | TCP_MISS |
.14.7. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_REFRESH_MISS | Integer | TCP_REFRESH_MISS |
.14.8. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_CLIENT_REFRESH_MISS | Integer | TCP_CLIENT_REFRESH_MISS |
.14.9. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_DENIED | Integer | TCP_DENIED |
.14.10. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_ERROR | Integer | TCP_ERROR |
.14.11. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_REDIRECT_HIT | Integer | TCP_REDIRECT_HIT |
cache.vhost.traffic.filesystem¶
OID = 1.3.6.1.4.1.40001.1.4.3.1.11.20
가상호스트의 File I/O 통계를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.1. [vhostMin] . [vhostIndex] |
requestHitRatio | Integer | Request Hit Ratio(100%) |
.2. [vhostMin] . [vhostIndex] |
Request Hit Ratio(10000%) | ||
.3. [vhostMin] . [vhostIndex] |
byteHitRatio | Integer | Byte Hit Ratio(100%) |
.4. [vhostMin] . [vhostIndex] |
Byte Hit Ratio(10000%) | ||
.5. [vhostMin] . [vhostIndex] |
outbound | Integer | File I/O로 보내는 평균 트래픽 (Bytes) |
.6. [vhostMin] . [vhostIndex] |
session | Integer | File I/O를 진행 중인 평균 Thread개수 |
.7 | requestHitAverage | OID | 평균 캐시 HIT결과 |
.7.1. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_HIT | Integer | TCP_HIT |
.7.2. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_IMS_HIT | Integer | TCP_IMS_HIT |
.7.3. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_REFRESH_HIT | Integer | TCP_REFRESH_HIT |
.7.4. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_REF_FAIL_HIT | Integer | TCP_REF_FAIL_HIT |
.7.5. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_NEGATIVE_HIT | Integer | TCP_NEGATIVE_HIT |
.7.6. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_MISS | Integer | TCP_MISS |
.7.7. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_REFRESH_MISS | Integer | TCP_REFRESH_MISS |
.7.8. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_CLIENT_REFRESH_MISS | Integer | TCP_CLIENT_REFRESH_MISS |
.7.9. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_DENIED | Integer | TCP_DENIED |
.7.10. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_ERROR | Integer | TCP_ERROR |
.7.11. [vhostMin] . [vhostIndex] |
requestHitAverage.TCP_REDIRECT_HIT | Integer | TCP_REDIRECT_HIT |
.8 | requestHitCount | OID | 캐시 HIT결과 개수 |
.8.1. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_HIT | Integer | TCP_HIT |
.8.2. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_IMS_HIT | Integer | TCP_IMS_HIT |
.8.3. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_REFRESH_HIT | Integer | TCP_REFRESH_HIT |
.8.4. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_REF_FAIL_HIT | Integer | TCP_REF_FAIL_HIT |
.8.5. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_NEGATIVE_HIT | Integer | TCP_NEGATIVE_HIT |
.8.6. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_MISS | Integer | TCP_MISS |
.8.7. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_REFRESH_MISS | Integer | TCP_REFRESH_MISS |
.8.8. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_CLIENT_REFRESH_MISS | Integer | TCP_CLIENT_REFRESH_MISS |
.8.9. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_DENIED | Integer | TCP_DENIED |
.8.10. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_ERROR | Integer | TCP_ERROR |
.8.11. [vhostMin] . [vhostIndex] |
requestHitCount.TCP_REDIRECT_HIT | Integer | TCP_REDIRECT_HIT |
.10. [vhostMin] . [vhostIndex] |
getattr.filecount | Integer | (getattr함수 호출) FILE로 응답한 회수 |
.11. [vhostMin] . [vhostIndex] |
getattr.dircount | Integer | (getattr함수 호출) DIR로 응답한 회수 |
.12. [vhostMin] . [vhostIndex] |
getattr.failcount | Integer | (getattr함수 호출) 실패로 응답한 회수 |
.13. [vhostMin] . [vhostIndex] |
getattr.timeres | Integer | (getattr함수 호출) 반응시간 (0.01ms) |
.14. [vhostMin] . [vhostIndex] |
open.count | Integer | open함수 호출 회수 |
.15. [vhostMin] . [vhostIndex] |
open.timeres | Integer | open함수 반응시간 (0.01ms) |
.16. [vhostMin] . [vhostIndex] |
read.count | Integer | read함수 호출 회수 |
.17. [vhostMin] . [vhostIndex] |
read.timeres | Integer | read함수 반응시간 (0.01ms) |
.18. [vhostMin] . [vhostIndex] |
read.buffersize | Integer | read함수에서 요청된 버퍼 크기 (Bytes) |
.19. [vhostMin] . [vhostIndex] |
read.bufferfilled | Integer | read함수에서 요청된 버퍼에 채운 크기 (Bytes) |
cache.vhost.traffic.dims¶
OID = 1.3.6.1.4.1.40001.1.4.3.1.11.21
가상호스트의 DIMS변환 통계를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.1. [vhostMin] . [vhostIndex] |
requests | Integer | DIMS 변환요청 횟수 |
.2. [vhostMin] . [vhostIndex] |
converted | Integer | 변환성공 횟수 |
.3. [vhostMin] . [vhostIndex] |
failed | Integer | 변환실패 횟수 |
.4. [vhostMin] . [vhostIndex] |
avgsrcsize | Integer | 원본 이미지의 평균 크기 (Bytes) |
.5. [vhostMin] . [vhostIndex] |
avgdestsize | Integer | 변환된 이미지의 평균 크기 (Bytes) |
.6. [vhostMin] . [vhostIndex] |
avgtime | Integer | 변환 소요시간 (ms) |
cache.vhost.traffic.compression¶
OID = 1.3.6.1.4.1.40001.1.4.3.1.11.22
가상호스트의 압축 통계를 제공한다.
OID | Name | Type | Description |
---|---|---|---|
.1. [vhostMin] . [vhostIndex] |
requests | Integer | 압축요청 횟수 |
.2. [vhostMin] . [vhostIndex] |
converted | Integer | 압축성공 횟수 |
.3. [vhostMin] . [vhostIndex] |
failed | Integer | 압축실패 횟수 |
.4. [vhostMin] . [vhostIndex] |
avgsrcsize | Integer | 원본 파일의 평균 크기 (Bytes) |
.5. [vhostMin] . [vhostIndex] |
avgdestsize | Integer | 압축된 파일의 평균 크기 (Bytes) |
.6. [vhostMin] . [vhostIndex] |
avgtime | Integer | 압축 소요시간 (ms) |
cache.view¶
OID = 1.3.6.1.4.1.40001.1.4.11.1
가상호스트 통계와 동일한 정보를 제공한다.
[viewIndex]
는 1부터 View개수의 범위를 가진다.
- 1.3.6.1.4.1.40001.1.4.3 - 가상호스트 통계
- 1.3.6.1.4.1.40001.1.4.11 - View 통계
12장. 로그¶
이 장에서는 로그를 다룬다. 서비스는 로그로 시작해서 로그로 끝난다. 로그는 금이며, 법이며, 분쟁지역의 평화유지군이다.
로그는 전역과 가상호스트로 구분된다. 모든 로그는 기록여부를 설정할 수 있으며, 공통속성을 가진다.
<XXX Type="time" Unit="1440" Retention="10" Compression="OFF">ON</XXX>
Type (기본: time)
,Unit (기본: 1440분)
로그 롤링조건을 설정한다.time
설정된unit
시간(단위: 분)마다 로그 파일을 롤링한다.size
설정된unit
크기(단위: MB)마다 로그 파일을 롤링한다.both
콤마(,)로 구분하여 시간과 크기를 동시에 설정한다. 예를 들어 Unit=”1440, 100”인 경우 시간이 24시간(1440분) 또는 100MB 인 경우 로그 파일을 롤링한다.
Retention (기본: 10개)
단위 로그파일을 최대 n개 유지한다.Compression (기본: OFF)
로그가 롤링될 때 압축을 진행한다. 예를 들어 access_20140715_0000.log파일이 롤링되면 access_20140715_0000.log.gz로 압축되어 저장된다.
Type
이 “time” , Unit
이 10이면 로그는 매 10분에 롤링된다.
예를 들어 서비스를 2:18분에 시작해도 로그는 매 10분인 2:20, 2:30, 2:40에 롤링된다.
마찬가지로 하루에 한번 매일 0시 0분에 롤링하려면 1440(60분 X 24시)으로 Unit
값으로 설정한다.
time
설정에서 로그는 하루에 한번 무조건 롤링되므로 Unit
의 최대값은 1440을 넘을 수 없다.

최대 값인 24시간(Unit=1440)시간마다 로그가 롤링되도록 설정했다면 다음 그림과 같이 로그가 기록된다.

Install 로그¶
설치/업데이트 시 모든 내용이 install.log에 기록된다. 이 로그는 별도의 설정이 없다.
#DownloadURL: http://foobar.com/ston/ston.2.0.0.rhel.2.6.32.x64.tar.gz
#DownloadTime: 13 sec
#Target: STON 2.0.0
#Date: 2014.03.03 16:48:35
Prepare for STON 2.0.0 install process
Stopping STON...
STON stopped
[Copying files]
`./fuse.conf' -> `/etc/fuse.conf'
`./libfuse.so.2' -> `/usr/local/ston/libfuse.so.2'
`./libtbbmalloc_proxy.so' -> `/usr/local/ston/libtbbmalloc_proxy.so'
`./start-stop-daemon' -> `/usr/sbin/start-stop-daemon'
`./libtbbmalloc_proxy.so.2' -> `/usr/local/ston/libtbbmalloc_proxy.so.2'
`./libtbbmalloc.so' -> `/usr/local/ston/libtbbmalloc.so'
`./libtbbmalloc.so.2' -> `/usr/local/ston/libtbbmalloc.so.2'
`./libtbb.so' -> `/usr/local/ston/libtbb.so'
`./libtbb.so.2' -> `/usr/local/ston/libtbb.so.2'
`./stond' -> `/usr/local/ston/stond'
`./stonx' -> `/usr/local/ston/stonx'
`./stonr' -> `/usr/local/ston/stonr'
`./stonu' -> `/usr/local/ston/stonu'
`./stonapi' -> `/usr/local/ston/stonapi'
`./server.xml.default' -> `/usr/local/ston/server.xml.default'
`./vhosts.xml.default' -> `/usr/local/ston/vhosts.xml.default'
`./ston_format.sh' -> `/usr/local/ston/ston_format.sh'
`./ston_diskinfo.sh' -> `/usr/local/ston/ston_diskinfo.sh'
`./wm.sh' -> `/usr/local/ston/wm.sh'
[Exporting config files]
#Export so directory
/usr/local/ston/ to ld.so.conf
#Export sysctl to /etc/sysctl.conf
vm.swappiness=0
vm.min_free_kbytes=524288
#Export sudoers for WM
Defaults !requiretty
winesoft ALL=NOPASSWD: /etc/init.d/ston stop, /etc/init.d/ston start, /bin/ps -ef
[Configuring STON daemon script]
STON deamon activate in run-level 2345.
[Installing sub-packages]
curl installed.
libjpeg installed.
libgomp installed.
rrdtool installed.
[Installing WM]
Stopping WM...
WM stopped
`./wm.server_default.xml' -> `/usr/local/ston/wm/tmp/conf/server_default.xml'
`./wm.vhost_default.xml' -> `/usr/local/ston/wm/tmp/conf/vhost_default.xml'
WM configuration found. Current WM port : 8500
PHP module for Legacy(CentOS 5.5) installed
`./libphp5.so.5.5' -> `/usr/local/ston/wm/modules/libphp5.so'
WM installation almost complete. Changing WM privileges.
Installation successfully complete
Info 로그¶
Info로그는 전역설정(server.xml)에 설정한다.
# server.xml - <Server><Cache>
<InfoLog Type="size" Unit="1" Retention="5">ON</InfoLog>
<InfoLog> (기본: ON, Type: size, Unit: 1)
STON의 동작과 설정변경에 대해 기록한다.
Deny 로그¶
Deny로그는 전역설정(server.xml)에 설정한다.
# server.xml - <Server><Cache>
<DenyLog Type="size" Unit="1" Retention="5">ON</DenyLog>
<DenyLog> (기본: ON, Type: size, Unit: 1)
서버 접근제어 에 의해 접근차단된 IP를 기록한다.
#Fields: date time c-ip deny 2012.11.15 07:06:10 1.1.1.1 AP 2012.11.15 07:06:26 2.2.2.2 GIN 2012.11.15 07:06:30 3.3.3.3 3.3.3.1-255
모든 필드는 공백으로 구분되며 각 필드의 의미는 다음과 같다.
date
날짜time
시간c-ip
클라이언트 IPdeny
차단조건
OriginError 로그¶
OriginError로그는 전역설정(server.xml)에 설정한다.
# server.xml - <Server><Cache>
<OriginErrorLog Type="size" Unit="5" Retention="5" Warning="OFF">ON</OriginErrorLog>
<OriginErrorLog> (기본: OFF, Type: size, Unit: 5, Warning: OFF)
모든 가상호스트의 원본서버에서 발생한 장애만을 기록한다. 장애는 접속장애와 전송장애를 의미하며 원본서버 배제/복구 결과가 기록된다.
#Fields: date time vhostname level s-domain s-ip cs-method cs-uri time-taken sc-error sc-resinfo 2012.11.15 07:06:10 [example.com] [ERROR] 192.168.0.13 192.168.0.13 GET /Upload/ProductImage/stock/1716439_SM.jpg 20110 Connect-Timeout - 2012.11.15 07:06:26 [example.com] [ERROR] 192.168.0.13 192.168.0.13 GET /Upload/ProductImage/stock/1716439_SM.jpg 20110 Connect-Timeout - 2012.11.15 07:06:30 [example.com] [ERROR] 192.168.0.13 192.168.0.13 GET /Upload/ProductImage/stock/1716439_SM.jpg 20110 Connect-Timeout - #2012.11.15 07:06:30 [example.com] 192.168.0.13 excluded from service #2012.11.15 07:06:31 [example.com] Origin server list: 192.168.0.14 #2012.11.15 07:11:11 [example.com] 192.168.0.13 recovered back in service #2012.11.15 07:11:12 [example.com] Origin server list: 192.168.0.13
모든 필드는 공백으로 구분되며 각 필드의 의미는 다음과 같다.
date
장애발생 날짜time
장애발생 시간vhostname
[가상호스트]level
[장애레벨(Error 또는 Warning)]s-domain
원본서버 도메인s-ip
원본서버 IPcs-method
STON이 원본서버에게 보낸 HTTP Methodcs-uri
STON이 원본서버에게 보낸 URItime-taken
장애가 발생 할때 까지 소요된 시간sc-error
장애의 종류sc-resinfo
장애발생시 서버 응답 정보(”,”문자로 구분)
Warning
속성이ON
이라면 다음과 잘못된 HTTP통신이 발생한 경우에 기록한다.2012.11.15 07:09:03 [example.com] [WARNING] 10.10.10.10 121.189.63.219 GET /716439_SM.jpg 20110 PartialResponseOnNormalRequest Res=206,Len=2635 2012.11.15 07:09:03 [example.com] [WARNING] 10.10.10.10 121.189.63.219 GET /716439_SM.jpg 20110 ClosedWithoutResponse -
잘못된 HTTP통신의 경우는 다음과 같다.
ClosedWithoutResponse
원본서버에 의한 연결종료. HTTP 응답을 받지 못했다.ClosedWhenDownloading
원본서버에 의한 연결종료. Content-Length 만큼 다운로드하지 못했다.NotPartialResponseOnRangeRequest
Range요청을 했으나 응답코드가 206이 아니다.DifferentContentLengthOnRangeRequest
요청한 Range와 Content-Length가 다르다.PartialResponseOnNormalRequest
Range요청이 아닌데 응답코드가 206이다.
SysLog 전송¶
syslog 프로토콜을 사용하여 로그를 UDP로 실시간 포워딩한다. 모든 로그에 대하여 syslog로 전송되도록 설정할 수 있다.
# server.xml - <Server><Cache>
<InfoLog SysLog="OFF">ON</InfoLog>
<DenyLog SysLog="OFF">ON</DenyLog>
<OriginErrorLog SysLog="OFF">ON</OriginErrorLog>
SysLog
OFF (기본)
syslog를 사용하지 않는다.ON
이 태그 하위에 설정된<SysLog>
로 로그를 전송한다.
다음은 <OriginErrorLog>
가 기록될 때 syslog를 설정하는 예제이다.
# server.xml - <Server><Cache>
<OriginErrorLog SysLog="ON">
<SysLog Priority="local3.info" Dest="192.168.0.1:514" />
<SysLog Priority="user.alert" Dest="192.168.0.2" />
<SysLog Priority="mail.debug" Dest="log.example.com" />
</OriginErrorLog>
<OriginErrorLog>
의SysLog
속성을ON
으로 설정한다.<OriginErrorLog>
의 하위에<SysLog>
태그를 생성한다. n대의 서버로 동시에 전송가능하다.<SysLog>
의Priority
속성을 설정한다. 이 표현은 syslog의 Facility Levels 과 Severity levels 의 조합으로 구성한다.<SysLog>
의Dest
속성을 설정한다. syslog수신서버를 의미하며 수신포트가 514인 경우 생략가능하다.
위 설정으로 기록된 sys로그 예제는 다음과 같다. syslog의 tag는 STON/{로그명}으로 기록된다.
Mar 12 11:24:24 192.168.0.1 STON/ORIGINERROR: 2013-03-12 14:09:20 [ERROR] [example.com] - 192.168.0.14 GET /1.gifd 1996 Connect-Timeout -
Mar 12 11:24:24 192.168.0.1 STON/ORIGINERROR: 2013-03-12 14:09:22 [ERROR] [example.com] - 192.168.0.14 GET /favicon.ico 1995 Connect-Timeout -
Mar 12 11:24:24 192.168.0.1 STON/ORIGINERROR: 2013-03-12 14:09:24 [ERROR] [example.com] - 192.168.0.14 GET /1.gifd22 2020 Connect-Timeout -
Mar 12 11:24:24 192.168.0.1 STON/ORIGINERROR: #2013 .03.12 14:09:24 [example.com] 192.168.0.14:102 excluded from service
Mar 12 11:24:24 192.168.0.1 STON/ORIGINERROR: #2013 .03.12 14:09:24 [example.com] Origin server list:
가상호스트별 로그저장¶
가상호스트별로 로그는 별도로 기록된다.
로그가 OFF
로 설정되어 있어도 로컬파일에만 써지지 않을 뿐이므로
Log Trace 는 정상동작한다.
# server.xml - <Server><VHostDefault>
# vhosts.xml - <Vhosts><Vhost>
<Log Dir="/cache_log">
... (생략) ...
</Log>
<Log>
Dir
속성으로 로그가 기록될 디렉토리를 설정한다. 로그는 설정한 디렉토리 하위의 가상호스트 디렉토리에 생성된다.
DNS 로그¶
원본서버로 Domain으로 설정되었다면 Resolving결과를 기록한다.
# server.xml - <Server><VHostDefault><Log>
# vhosts.xml - <Vhosts><Vhost><Log>
<Dns Type="size" Unit="10" Retention="10" SysLog="OFF" Compression="OFF">ON</Dns>
#Fields: date time domain ttl ip-list ip-count time-taken result
2014-07-30 12:10:33 example.com 157 173.194.127.15,173.194.127.23,173.194.127.24,173.194.127.31 4 5007 success
2014-07-30 12:10:38 example.com 152 173.194.127.23,173.194.127.24,173.194.127.31,173.194.127.15 4 9 success
2014-07-30 12:11:03 example.com 127 173.194.127.31,173.194.127.15,173.194.127.23,173.194.127.24 4 15007 success
2014-07-30 12:12:53 example.com 17 173.194.127.15,173.194.127.23,173.194.127.24,173.194.127.31 4 6 success
2014-07-30 12:23:16 test.com 0 - 0 10008 fail
2014-07-30 12:23:21 test.com 0 - 0 5007 fail
2014-07-30 12:23:26 test.com 0 - 0 5011 fail
2014-07-30 12:24:38 example.com 152 173.194.127.23,173.194.127.24,173.194.127.31,173.194.127.15 4 9 success
2014-07-30 12:25:03 example.com 127 173.194.127.31,173.194.127.15,173.194.127.23,173.194.127.24 4 15007 success
모든 필드는 공백으로 구분되며 각 필드의 의미는 다음과 같다.
date
날짜time
시간domain
대상 Domainttl
레코드 유효시간(Time To Live)ip-list
IP 리스트ip-count
IP 개수time-taken
수행시간result
success 또는 fail
Access 로그¶
모든 클라이언트의 HTTP 트랜잭션을 기록한다. 로그 기록 시점은 HTTP 트랜잭션이 완료되는 시점이며 전송완료 또는 전송중단 시점을 의미한다.
# server.xml - <Server><VHostDefault><Log>
# vhosts.xml - <Vhosts><Vhost><Log>
<Access Type="time" Unit="1440" Retention="10" XFF="on" Form="ston" Local="Off">ON</Access>
XFF
ON (기본)
클라이언트가 보낸 XFF(X-Forwarded-For)헤더 값과 클라이언트 IP를 같이 기록한다. 없다면OFF
와 같다.OFF
클라이언트 IP를 기록한다.TrimCIP
XFF헤더가 없을 경우 클라이언트 IP를, 있는 경우 (클라이언트 IP를 제외한) XFF헤더만을 기록한다.
Form
ston (기본)
W3C표준 + 확장필드apache
Apache 형식iis
IIS 형식custom
admin-log-access-custom
Local
OFF (기본)
로컬통신(Loopback)은 기록하지 않는다.ON
로컬통신(Loopback)도 기록한다.
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) sc-status sc-bytes time-taken cs-referer sc-resinfo cs-range sc-cachehit cs-acceptencoding session-id sc-content-length
2012.06.27 16:52:24 220.134.10.5 GET /web/h.gif - 80 - 61.50.7.9 Chrome/19.0.1084.56 200 98141 5 - Bypass+gzip+SSL3 - TCP_HIT gzip+deflate 7 1273735
2012.06.27 16:52:26 220.134.10.5 GET /favicon.ico - 80 - 61.50.7.9 Chrome/19.0.1084.56 200 949 2 - - - TCP_HIT gzip+deflate 35 14875
2012.06.27 17:00:06 220.168.0.13 GET /setup.Eexe - 80 - 61.168.0.102 Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/536.11+(KHTML,+like+Gecko)+Chrome/20.0.1132.57+Safari/536.11 206 20971800 7008 - - 398458880-419430399 TCP_HIT - 41 89764358
모든 필드는 공백으로 구분되며 각 필드의 의미는 다음과 같다.
date
HTTP 트랜잭션이 완료된 날짜time
HTTP 트랜잭션이 완료된 시간s-ip
서버 IPcs-method
클라이언트가 보낸 HTTP Methodcs-uri-stem
클라이언트가 보낸 URL중 QueryString을 제외한 부분cs-uri-query
클라이언트가 보낸 URL중 QueryStrings-port
서버 포트cs-username
클라이언트 usernamec-ip
클라이언트 IP`` XFF설정이 “ON”이라면 X-Forwarded-For헤더 값과 클라이언트 IP를 기록한다.cs(User-Agent)
클라이언트가 보낸 HTTP User-Agentsc-status
서버 응답코드.sc-bytes
서버가 보낸 Bytes (헤더 + 컨텐츠)time-taken
HTTP트랜잭션이 완료될 때까지 소요된 전체시간(밀리세컨드)cs-referer
클라이언트가 보낸 HTTP Referersc-resinfo
부가 정보. “+”문자로 구분된다. 인코딩된 컨텐츠를 서비스했다면 인코딩 옵션(gzip 또는 deflate)이 명시된다. 보안 통신이라면 SSL 프로토콜 버전(SSL3, TLS1, TLS1.1, TLS1.2)이 명시된다. 바이패스한 통신이라면 “Bypass”가 명시된다.cs-range
클라이언트가 보낸 Range 헤더를 기록한다.sc-cachehit
캐시 HIT결과.cs-acceptencoding
클라이언트가 보낸 Accept-Encoding헤더.session-id
HTTP 클라이언트 세션 ID (unsigned int64)sc-content-length
서버 응답 Content-Length 헤더 값
Access로그는 전송 성공/실패 여부에 상관없이 모든 HTTP 트랜잭션을 기록한다.
HTTP 트랜잭션은 클라이언트가 HTTP요청을 보낼 때 시작된다.
STON이 클라이언트에게 응답을 보내기 전에 HTTP연결이 종료된다면 HTTP 트랜잭션 역시
종료된 것으로 간주한다.
로그에는 sc-status
와 sc-bytes
가 0으로 기록된다.
주로 STON이 원본서버로부터 응답을 받기 전에 클라이언트가 연결을 종료하는 경우 이런
로그가 기록된다.
사용자정의 Access 로그포맷¶
Access 로그형식을 사용자정의 로그로 설정한다.
# server.xml - <Server><VHostDefault><Log>
# vhosts.xml - <Vhosts><Vhost><Log>
<Access Form="custom">ON</Access>
<AccessFormat>%a %A %b id=%{userid}C %f %h %H "%{user-agent}i" %m %P "%r" %s %t %T %X %I %O %R %e %S %K</AccessFormat>
<Access>
의Form
속성을custom
으로 설정한다.<AccessFormat>
사용자정의 로그 형식.
위 예제의 경우 다음과 같이 Access로그가 기록된다. (#Fields는 기록하지 않는다.)
192.168.0.88 192.168.0.12 163276 id=winesoft; image.jpg example.com HTTP "STON" GET 80 "GET /ston/image.jpg?type=png HTTP/1.1" 200 2014-04-03 21:21:54 1 C 204 163276 1 2571978 TCP_MISS HTTP/1.1
192.168.0.88 192.168.0.12 63276 id=winesoft; vod.mp4 example.com HTTP "STON" POST 80 "GET /ston/vod.mp4?start=10 HTTP/1.1" 200 2014-04-03 21:21:54 12 C 304 363276 2 2571979 TCP_REFRESH_HIT HTTP/1.1
192.168.0.88 192.168.0.12 3634276 id=ston; news.html example.com HTTPS "STON" GET 443 "GET /news.html HTTP/1.1" 200 2014-04-03 21:21:54 30 X 156 2632576 1 2571980 TCP_MISS HTTP/1.1
192.168.0.88 192.168.0.12 6332476 id=winesoft; style.css example.com HTTP "STON" HEAD 80 "GET /style.css HTTP/1.1" 200 2014-04-03 21:21:54 10 X 234 653276 2 2571981 TCP_REFRESH_HIT HTTP/1.1
192.168.0.88 192.168.0.12 6276 id=ston; ui.js example.com HTTP "STON" GET 80 "GET /ui.js HTTP/1.1" 200 2014-04-03 21:21:54 1 X 233 63276 1 2571982 TCP_MISS HTTP/1.1
192.168.0.88 192.168.0.12 626 id=winesoft; hls.m4u8 example.com HTTP "STON" GET 80 "GET /hls.m4u8 HTTP/1.1" 200 2014-04-03 21:21:54 2 X 124 6312333276 2 2571983 TCP_REFRESH_HIT HTTP/1.1
Apache로그 형식 을 기반으로 개발되었으며 일부 확장필드가 있다. 각 필드의 구분자에는 제한이 없지만 Space를 사용할 경우, User-Agent처럼 Space가 포함될 수 있는 필드는 따옴표(”...”)로 묶어서 설정한다.
%...a
클라이언트 IP192.168.0.66
%...A
서버IP 주소192.168.0.14
%...b
HTTP헤더를 제외한 전송 바이트수1024
%...{foobar}C
서버가 수신한 요청의 Foobar 쿠키의 내용%{id=}c 로 입력하면 Cookie 에서 id=에 해당하는 값을 기록
%...D
요청을 처리하는데 걸린 시간(MS)3000
%...f
파일명/mp4/iu.mp4 라면 iu.mp4를 기록
%...h
HostNameexample.com
%...H
요청 프로토콜http 또는 https
%...{foobar}i
서버가 수신한 요청에서 foobar: 헤더의 내용%{User-Agent}i 로 입력 할 경우 User-Agent의 값을 기록
%...m
요청 MethodGET 또는 POST 또는 HEAD
%...P
Server PORT80
%...q
QueryStringId=10&value=20
%...r
요청의 첫번째 줄(Request Line)GET /img.jpg HTTP/1.1
%...s
응답코드200
%...t
STON 기본 시간형식2014-01-01 15:27:02
%...{format}t
Format에 정의된 날짜 형식%{%Y-%m-%d %H:%M:%S}T 로 입력하면 2014-08-07 06:12:23으로 기록.
%...T
TimeTaken(초단위)10
%...U
ShortURI/img/img.jpg
%...u
FullURI/img/img.jpg?session=1232&id=37
%...X
트랜잭션이 완료되었을 때의 상태X
응답이 완료되기 전에 종료C
응답이 완료 되었음
C
%...I
요청헤더를 포함한 수신바이트2048
%...O
응답헤더를 포함한 송신바이트2048
%...R
응답시간(MS)2
%...e
Session-ID1
%...S
캐싱 HIT 결과TCP_HIT
%...K
요청 HTTP 버전HTTP/1.1
%...y
요청 HTTP 헤더 크기488
%...z
응답 HTTP 헤더 크기362
설정한 필드의 값이 존재하지 않으면 - 로 표기한다. 형식이 잘못되었다면 STON 기본 포맷(Form=”ston”)으로 동작한다.
위 표에서 각 필드의 ...에는 (e.g. “%h %U %r %b) 아무것도 명시하지 않거나, 기록 조건을 명시할 수 있다(조건을 만족하지 않으면 - 로 기록). 조건은 HTTP 상태코드 목록으로 설정하거나 !로 NOT 조건을 설정할 수 있다.
다음 예제는 400(Bad Request) 오류 또는 501(Not Implemented) 오류 일 때만 User-agent를 기록한다.
"%400,501{User-agent}i"
다음 예제는 정상적인 상태가 아닌 모든 요청에 대해 Referer를 로그에 남긴다.
"%!200,304,302{Referer}i"
Origin 로그¶
원본서버의 모든 HTTP 트랜잭션을 기록한다. 기록 시점은 HTTP 트랜잭션이 완료되는 시점이며 전송완료 또는 전송중단 시점을 의미한다.
# server.xml - <Server><VHostDefault><Log>
# vhosts.xml - <Vhosts><Vhost><Log>
<Origin Type="time" Unit="1440" Retention="10" Local="Off">ON</Origin>
#Fields: date time cs-sid cs-tcount c-ip cs-method s-domain cs-uri s-ip sc-status cs-range sc-sock-error sc-http-error sc-content-length cs-requestsize sc-responsesize sc-bytes time-taken time-dns time-connect time-firstbyte time-complete cs-reqinfo cs-acceptencoding sc-cachecontrol s-port sc-contentencoding session-id session-type
2012.06.27 17:40:00 357 899 192.168.0.13 GET i.example.com /t/2.gif 115.71.9.136 200 - - - 3874 197 271 3874 20 0 0 17 3 - gzip+deflate - 80 gzip 7 cache
2012.06.27 17:40:00 357 900 192.168.0.13 GET i.example.com /ex1.gif 115.71.9.136 200 - - - 5673 223 272 5673 24 0 0 21 3 - - - 80 - 8 cache
2012.06.27 17:40:00 357 901 192.168.0.13 GET i.example.com /exB.jpg 115.71.9.136 200 - - - 8150 189 273 8150 13 0 0 9 4 Bypass - - 80 - 7 cache
#[ERROR:01] 2012.06.27 17:40:01 220.73.216.5 220.73.216.5 GET /web/nmb/img/main/v1/h1.gif 1824 Connect-Timeout - 11 cache
2012.06.27 17:40:00 357 901 192.168.0.13 GET i.example.com /exB1.jpg 115.71.9.136 200 - - - 8150 189 273 8150 13 0 0 9 4 - max-age=3600 80 - 12 cache
2012.06.27 17:40:00 357 901 192.168.0.13 GET i.example.com /exB2.jpg 115.71.9.136 200 - - - 8150 189 273 8150 13 0 0 9 4 - no-cache 80 - 35 cache
2012.06.27 17:40:00 357 901 192.168.0.13 GET i.example.com /exB3.jpg 115.71.9.136 200 - - - 8150 189 273 8150 13 0 0 9 4 - - 80 - 35 cache
원본서버에 장애가 발생했다면 #[ERROR:xx]로 시작하는 에러 로그가 기록된다. 모든 필드는 공백으로 구분되며 각 필드의 의미는 다음과 같다.

원본 시간측정 구간
date
HTTP 트랜잭션이 완료된 날짜time
HTTP 트랜잭션이 완료된 시간cs-sid
세션의 고유ID. 같은 세션을 통해 처리된(재사용된) HTTP 트랜잭션은 같은 값을 가진다.cs-tcount
트랜잭션 카운트. 이 HTTP 트랜잭션이 현재 세션에서 몇 번째로 처리된 트랜잭션인지 기록한다. 같은cs-sid
값을 가지는 트랜잭션이라면 이 값은 중복될 수 없다.c-ip
STON의 IPcs-method
원본서버에게 보낸 HTTP Methods-domain
원본서버 도메인cs-uri
원본서버에게 보낸 URIs-ip
원본서버 IPsc-status
원본서버 HTTP 응답코드cs-range
원본서버에게 보낸 Range요청 값sc-sock-error
소켓 에러코드(1=전송실패, 2=전송지연, 3=연결종료)sc-http-error
원본서버가 4xx 또는 5xx응답을 줬을 때 응답코드를 기록sc-content-length
원본서버가 보낸 Content Lengthcs-requestsize (단위: Bytes)
원본서버로 보낸 HTTP 요청 헤더 크기sc-responsesize (단위: Bytes)
원본서버가 응답한 HTTP 헤더 크기sc-bytes (단위: Bytes)
수신한 컨텐츠 크기(헤더 제외)time-taken (단위: ms)
HTTP 트랜잭션이 완료될 때까지 소요된 전체시간. 세션 재사용이 아니라면 소켓 접속시간까지 포함한다.time-dns (단위: ms)
DNS쿼리에 소요된 시간time-connect (단위: ms)
원본서버와 소켓 Established까지 소요된 시간time-firstbyte (단위: ms)
요청을 보내고 응답이 올때까지 소요된 시간time-complete (단위: ms)
첫 응답부터 완료될 때까지 소요된 시간cs-reqinfo
부가 정보. “+”문자로 구분한다. 바이패스한 통신이라면 “Bypass”, Private바이패스라면 “PrivateBypass”로 기록된다.cs-acceptencoding
원본서버에 압축된 컨텐츠를 요청하면 “gzip+deflate”로 기록된다.sc-cachecontrol
원본서버가 보낸 cache-control헤더s-port
원본서버 포트sc-contentencoding
원본서버가 보낸 Content-Encoding헤더session-id
원본서버 요청을 발생시킨 HTTP 클라이언트 세션 ID (unsigned int64)session-type
원본서버에 요청한 세션 타입cache
캐싱용도로 사용된 세션recovery
장애감지와 복구 에서 복구용도로 사용된 세션healthcheck
Health-Checker 가 사용한 세션
Monitoring 로그¶
5분 평균 통계를 기록한다.
# server.xml - <Server><VHostDefault><Log>
# vhosts.xml - <Vhosts><Vhost><Log>
<Monitoring Type="size" Unit="10" Retention="10" Form="json">ON</Monitoring>
Form
로그형식을 지정한다. (json
또는xml
)
FileSystem 로그¶
18장. File System 을 통해 발생하는 모든 File I/O 트랜잭션을 기록한다.
# server.xml - <Server><VHostDefault><Log>
# vhosts.xml - <Vhosts><Vhost><Log>
<FileSystem Type="time" Unit="1440" Retention="10">ON</FileSystem>
File I/O 트랜잭션이 종료될 때 기록된다. 트랜잭션 종료 시점은 cs-method의 형태에 따라 달라진다.
#Fields: date time cs-method cs-path sc-status sc-bytes response-time time-taken sc-cachehit attr session-id
2012.06.27 16:52:24 ATTR /t 200 0 100 100 TCP_HIT FOLDER 1
2012.06.27 16:52:24 ATTR /t/2.gif 200 0 100 100 TCP_HIT FILE 1
2012.06.27 16:52:24 OPEN /file.txt 200 0 100 2000 TCP_HIT FILE 2
2012.06.27 16:52:24 READ /file.txt 200 1024768 100 2000 TCP_HIT FILE 2
date
File I/O 트랜잭션이 완료된 날짜time
File I/O 트랜잭션이 완료된 시간cs-method
File I/O 접근 형태. 다음 3가지 중 하나를 가진다.ATTR
getattr함수 호출. 함수가 리턴될 때 로그 기록OPEN
파일은 열었지만 READ 하지 않음. 파일이 닫힐 때 로그 기록READ
파일을 열고 READ 하였음. 파일이 닫힐 때 로그 기록
cs-path
접근 경로sc-status
응답코드. 정상적인 서비스(200)를 제외한 처리 실패코드는 다음과 같다.200
정상 서비스301
바이패스 필요302
서비스 거부303
Redirect 필요400
잘못된 요청401
가상호스트를 찾지 못했음402
원본으로부터 초기화 실패500
객체 초기화 실패501
객체 Open실패502
저장경로 생성실패503
메모리 초기화 실패504
Emergency 상태600
파일 서비스 대기 중 Timeout601
파일 데이터 서비스 대기 중 Timeout602
파일 서비스 대기 중 파일초기화 실패603
파일 데이터 서비스 대기 중 데이터 초기화 실패701
잘못된 Offset702
파일의 특정 영역을 로딩 실패703
Not enough memory704
원본세션 생성 실패
sc-bytes
Read된 크기response-time
함수 호출 ~ 서비스객체를 연결하는데 소요된 시간time-taken
함수 호출 ~ File I/O Transaction이 완료되는데 소요된 시간.sc-cachehit
캐시 HIT결과.attr
FILE 또는 FOLDERsession-id
File I/O 세션 ID (unsigned int64)주석
session-id
는 Client(HTTP 또는 File I/O) Context가 생성될 때 할당된다. 일반적인 파일 처리 과정인 Open -> Read -> Close에서는 Open시점에 Client Context가 생성되며 Close시점에 파괴된다. 반면 getattr함수는 원자성(Atomic)함수이므로 매번 Client Context가 생성/파괴되어 항상 새로운 session-id를 할당 받는다.
FTP 전송¶
로그가 롤링될 때 지정된 FTP클라이언트를 통해 로그를 업로드 한다.
FTP 클라이언트¶
FTP 클라이언트를 설정한다. 롤링된 로그를 실시간으로 FTP서버로 업로드한다.

FTP클라이언트 구조와 동작
FTP 클라이언트는 위 그림과 같이 STON외부에 존재한다. STON은 로컬에 존재하는 로그를 FTP클라이언트 큐에 입력할 뿐 FTP의 동작에는 관여하지 않는다. FTP클라이언트는 자신의 설정에 따라 업로드를 진행한다.
FTP 클라이언트는 전역설정(server.xml)에 설정한다.
# server.xml - <Server>
<Ftp Name="backup1">
<Mode>Passive</Mode>
<Address>ftp.winesoft.co.kr:21</Address>
<Account>
<ID>test</ID>
<Password>12345abc</Password>
</Account>
<ConnectTimeout>10</ConnectTimeout>
<TransferTimeout>600</TransferTimeout>
<TrafficCap>0</TrafficCap>
<DeleteUploaded>OFF</DeleteUploaded>
<BackupOnFail>OFF</BackupOnFail>
<UploadPath>/log_backup/%v/%s-%e.%p.log</UploadPath>
<Transfer Time="Rotate" />
</Ftp>
<Ftp Name="backup2">
<Mode>Active</Mode>
<Address>192.168.0.14:21</Address>
<Account>
<ID>test</ID>
<Password>qwerty</Password>
</Account>
<ConnectTimeout>3</ConnectTimeout>
<TransferTimeout>100</TransferTimeout>
<TrafficCap>10240</TrafficCap>
<DeleteUploaded>ON</DeleteUploaded>
<BackupOnFail>ON</BackupOnFail>
<Transfer Time="Static">04:00</Transfer>
</Ftp>
<Ftp>
FTP 클라이언트를 설정한다.Name
속성으로 고유의 이름을 설정한다.Mode (기본: Passive)
접속모드 (Passive
또는Active
)Address
FTP주소.Account
FTP 계정. 만약 비밀번호(예를 들어 qwerty)를 암호화하고 싶다면 다음 API 사용한다./command/encryptpassword?plain=qwerty
암호화된 비밀번호는 다음과 같이 설정한다.
<Password Type="enc">dXR9k0xNUZVVYQsK5Bi1cg==</Password>
ConnectTimeout
연결대기 시간TransferTimeout
전송대기 시간TrafficCap (단위: KB)
0보다 큰 값으로 설정할 경우 전송 최대 대역폭을 설정한다.DeleteUploaded (기본: OFF)
전송완료 후 해당로그를 삭제한다.BackupOnFail (기본: OFF)
전송실패 시 로그가 삭제되지 않도록 해당로그를 다음 경로에 백업한다./usr/local/ston/stonb/backup/
백업된 로그는 재전송하지 않으며 관리자가 삭제하기 전까지 삭제되지 않는다.
UploadPath
업로드 경로를 설정한다. 별도로 설정하지 않으면 “/가상호스트/” 에 업로드 한다. example.com의 로그는 /example.com/ 디렉토리에 업로드된다.%{time format}s
로그 시작 시간%{time format}e
로그 끝 시간%p
prefix%v
가상호스트 이름%h
장비 HOST 이름
예를 들어 다음과 같이 설정했다면
# server.xml - <Server><Ftp> <UploadPath>/log_backup/%v/%s-%e.%p.log</UploadPath>
업로드 경로는 다음과 같다.
/log_backup/example.com/200140722_0000-200140722_2300.access.log
Transfer
로그 전송시간을 지정한다.Type
속성에 따라 값의 형식이 달라진다.Rotate (기본)
롤링되면 바로 전송한다. 값을 가지지 않는다.Static
하루에 한번 지정된 시간에 전송한다. 예를 들어 04:00으로 설정됐다면 새벽 4시에 전송을 시작한다.Interval
일정시간 간격으로 전송한다. 예를 들어 4로 설정했다면 4시간 간격으로 로그를 전송한다.
전송시간을 설정할 경우 해당 시점에 로그가 롤링되지 않도록 적절히 로그관리 정책을 구성해야 한다.
FTP클라이언트는 curl을 사용한다.
FTP 로그¶
FTP로그는 /usr/local/ston/sys/stonb/stonb.log에 통합하여 저장된다.
#Fields: date time local-path cs-url file-size time-taken sc-status sc-error-msg
2014-04-23 17:10:20 /ston_log/winesoft.co.kr/origin_20140423_080000.log ftp://ftp.winesoft.co.kr:21/winesoft.co.kr/origin_20140423_080000.log 381 10006 fail "curl: (7) couldn't connect to host"
2014-04-23 17:10:20 /ston_log/winesoft.co.kr/access_20140423_1700.log ftp://192.168.0.14:21/winesoft.co.kr/access_20140423_1700.log 260 60 success "-"
2014-04-23 17:11:00 /ston_log/winesoft.co.kr/origin_20140423_080000.log ftp://ftp.winesoft.co.kr:21/winesoft.co.kr/origin_20140423_080000.log 381 10008 fail "curl: (7) couldn't connect to host"
2014-04-23 17:11:00 /ston_log/winesoft.co.kr/filesystem_20140423_080000.log ftp://192.168.0.14:21/winesoft.co.kr/filesystem_20140423_080000.log 179 60 success "-"
모든 필드는 공백으로 구분되며 각 필드의 의미는 다음과 같다.
date
날짜time
시간local-path
전송할 로그이 로컬경로cs-url
전송할 FTP주소file-size
전송 파일크기time-taken (단위: ms)
전송 소요시간sc-status
전송 성공/실패(success 또는 fail)sc-error-msg
전송 실패 시 curl 에러 메세지
로그 FTP전송¶
로그가 롤링될 때 지정된 FTP 클라이언트 를 통해 업로드 한다. 콤마(,)로 구분하면 여러 FTP 클라이언트 를 동시에 사용할 수 있다.
# server.xml - <Server><VHostDefault>
# vhosts.xml - <Vhosts><Vhost>
<Log>
<Access Ftp="backup1, backup2">ON</Access>
<Origin Ftp="backup_org">ON</Origin>
<Monitoring Ftp="backup1">ON</Monitoring>
<FileSystem Ftp="backup2">ON</FileSystem>
</Log>
Ftp
사용할 FTP 클라이언트
ftp://{FTP서버 주소}/{가상호스트이름}/{롤링된 로그 이름} 으로 로그를 업로드 한다. 예를 들어 ftp.dummy.com서버에 가상호스트 example.com의 롤링된 로그(access_20140424_0000.log)를 업로드하는 주소는 ftp://ftp.dummy.com/example.com/access_20140424_0000.log가 된다.
13장. WM (Web Management)¶
이 장에서는 Web Management(이하 WM)를 소개한다. WM은 API를 기반으로 동작하는 Web 관리 툴이다. WM을 통하여 직관적으로 서비스를 구성할 수 있을 뿐만 아니라 클러스터를 구성하여 많은 수의 STON을 통합관리 할 수 있다.
STON을 설치하면 /usr/local/ston/wm 경로에 WM이 설치된다. WM은 Apache 2.2.24 + PHP 5.3.24으로 구현되었다. Apache를 사용하므로 /usr/local/ston/wm/conf/httpd.conf 파일을 편집하여 원하시는 구성(예를 들어 HTTPS)으로 변경이 가능하다. WM과 STON은 밀접한 연관을 가지지 않는다. 다음 그림처럼 WM은 STON의 설정파일과 API만을 사용하여 STON의 동작을 구성한다.

WM은 STON의 설정파일과 API를 사용한다.
저희는 이와 유사한 방식으로 WM을 능가하는 더 나은 관리기법이 존재할 것이라 생각한다.
접속¶
WM은 기본적으로 8500번 포트를 사용한다. 설치된 STON의 IP가 192.168.0.100이라면 WM접근 주소는 http://192.168.0.100:8500이 된다. 앞서 언급한 대로 httpd.conf 파일을 변경하면 고객사에 맞추어 커스터마이징이 가능하다.

WM 접속초기화면
최신버전 업데이트¶
최신버전이 릴리스되면 다음과 같이 “새로운 업데이트가 있습니다” 메시지가 표시된다.

새로운 업데이트가 있습니다.
메시지를 클릭하시면 최신버전으로 업데이트할 수 있는 페이지가 표시된다. 현재 서비스 상태에 따라 업데이트 안전도 여부가 표시된다.

WM 업데이트하면 위험합니다.
업데이트가 완료되면 모든 서비스가 자동으로 재시작 된다.
메뉴 구성¶
메뉴는 Mouse-Click에 따라 확장/축소가 되는 Drop Down메뉴로 구성된다.

WM 메뉴
전역설정
전역설정(server.xml)에서 가상호스트 기본설정을 제외한 모든 기능을 설정한다.
가상호스트 관리
가상호스트의 추가/중지/삭제를 할 수 있으며 서비스 중인 모든 가상호스트 상태를 한눈에 볼 수 있다.
클러스터
클러스터를 구성/관리/파괴할 수 있으며 같은 클러스터의 모든 서비스를 서버별, 서비스별로 볼 수 있다.
컨텐츠제어
Purge와 같이 서비스 중인 컨텐츠에 대하여 제어할 수 있다.
서버 상태
시스템 상태와 같은 전역자원을 모니터링 한다. 모든 Graph는 전역자원 Graph를 사용한다.
서비스 상태
가상호스트의 서비스 상태를 모니터링 한다. 모든 Graph는 가상호스트 Graph를 사용한다.
파일 시스템
STON을 Linux VFS에 Mount할 수 있다.
가상호스트 관리¶
서비스하는 모든 가상호스트에 대하여 상세히 설정하며 신규 가상호스트를 추가한다. 모든 가상호스트는 따로 명시적으로 설정을 변경하지 않는 이상 기본 가상호스트(VHostDefault)의 설정을 사용한다. 이는 객체지향의 상속(Inheritance)과 같은 개념이다. 서비스 가상호스트는 대부분의 항목을 재정의(Overriding)할 수 있다.
신규¶
새롭게 서비스할 가상호스트를 생성한다. 클러스터가 설정되어 있는 경우 모든 서버에 가상호스트를 동시생성 할 수 있다. 모든 가상호스트는 기본 가상호스트(VHostDefault)를 상속받으므로 가상호스트명과 원본서버 주소만 설정하면 곧바로 서비스 투입이 가능하다. 8가지의 하위 설정이 있으며 펼쳐보기 버튼을 눌러 상세 설정으로 확장할 수 있다.

WM 가상호스트 관리 - 신규
목록¶
서비스 중인 모든 가상호스트 상태를 모니터링할 수 있다. 가상호스트별로 시작/중지가 가능하다. 클러스터가 설정되어 있다면 모든 서버의 가상호스트를 동시에 제어할 수 있다. 또한 기본가상호스트를 선택할 수 있다.

WM 가상호스트 관리 - 목록
상세설정¶
기본 가상호스트(VHostDefault)와 개별 가상호스트에 대해 설정한다. 좌측상단의 콤보박스를 선택하여 가상호스트를 선택할 수 있다. “Default 가상호스트” 는 모든 가상호스트가 상속받는 기본 설정이다. 그러므로 별도로 재정의하지 않은 설정의 경우 “Default 가상호스트”를 변경하면 변경된 설정이 반영된다.

WM 가상호스트 설정 - 상단메뉴
위 그림처럼 많은 하위메뉴가 제공되며 현재 선택된 하위메뉴가 붉은 색으로 표시된다. 각 메뉴 클릭시 아래 그림처럼 상세설정 페이지가 제공된다. 모든 설정은 “적용” 또는 “Cluster전체적용” 버튼을 눌러야 반영된다.

WM 가상호스트 설정 - 원본서버
여기서 설정하는 거의 모든 항목은 재정의될 수 있는 설정이므로 이에 대한 명확한 이해가 필요하다. 예를 들어 기본 가상호스트의 TTL값이 60으로 설정된 경우 모든 가상호스트는 이 값을 상속받는다. 하지만 명확하게 이 값을 재정의 하는 경우 해당 가상호스트에 한하여 재정의된 값을 사용하게 된다.

다음과 같이 3가지 경우가 존재할 수 있다.
다른 값으로 재정의
A의 경우처럼 기본 값은 60이지만 180으로 재정의할 경우 A사용자는 180으로 서비스된다. 기본 가상호스트 설정이 변경되어도 영향을 받지 않는다.
같은 값으로 재정의
B의 경우처럼 기본 값과 같은 값으로 설정하여도 재정의로 판단하여 B사용자는 60으로 서비스된다. 추후 기본 가상호스트의 TTL값이 30으로 변경되더라도 재정의가 되어 있으므로 B사용자의 설정(60)은 영향을 받지 않는다.
재정의하지 않음
C의 경우처럼 생략된 경우 기본 가상호스트 설정을 상속받아 C사용자는 60으로 서비스된다. 추후 기본 가상호스트의 TTL값이 30으로 변경되면 C사용자도 30으로 서비스된다.
WM에서는 색으로 재정의를 구분한다. 기본 가상호스트의 설정을 그대로 사용하는 경우 흰색배경으로 표시된다. 재정의된 값은 살구색으로 표시되어 기본값과 구분된다. 모든 재정의 설정의 우측에는 X버튼이 제공된다. 이 버튼을 클릭하여 재정의를 해지한다.
클러스터¶
여러 대의 STON을 하나의 클러스터로 통합하여 일괄적으로 관리/운영할 수 있다. 모든 STON은 동등한 관계로 설정되기 때문에 클러스터에 포함된 어떤 STON으로 로그인 하여도 클러스터 전체를 관리할 수 있다.
구성¶
클러스터를 생성하거나 이미 존재하는 클러스터에 다른 서버를 추가할 수 있다. 클러스터 추가에는 WM계정의 인증절차가 필요하다. 만약 같은 계정(아이디와 비밀번호)으로 WM이 구성되어 있다면 인증절차는 생략된다.

신규 클러스터 생성

클러스터 목록
클러스터가 구성되면 가상호스트 관리시 “Cluster전체적용” 버튼으로 일괄설정이 가능하다. 또한 클러스터에 소속된 서버끼리 간편하게 모든 설정을 복제할 수 있다. 특정 서버를 다른 클러스터에 참여시키고 싶으면 탈퇴 후 재구성해야 한다.
전용 포트분리¶
최초 설치시 WM과 클러스터 포트가 같은 포트를 사용한다. 이 방식은 WM계정만으로 클러스터링 구성이 가능하다는 장점이 있지만 접근 IP를 제한하는 환경에서는 문제가 될 수 있다.
- 보안상의 이유로 WM을 일부 IP에서만 접근되도록 제한한다.
- 클러스터링을 위해서는 모든 서버들이 서로 다른 서버들의 IP를 허가해주어야 한다.
- (CDN 처럼) 서버 수가 매우 많거나 서버들의 IP가 유동적인 경우 IP목록을 작성할 수 없다.
클러스터 포트를 분리하여 이 문제를 해결할 수 있다. 서버들끼리 신원은 WM 계정이 아닌 라이선스를 통해 확인된다. 같은 라이선스를 가진 서버들끼리만 클러스터가 가능해져 보안성이 높아진다.
1. [Apache 서버] httpd.conf 멀티 Port설정
(기본 설치라면) /usr/local/ston/wm/conf/httpd.conf 파일을 열어 다음과 같이 포트를 추가한다.

저장 후 반영을 위해 Apache서버를 재시작한다.
2. [WM] 클러스터 구성
정상적으로 멀티포트 구성이 되었다면 다음과 같이 “클러스터 포트 분리” 버튼이 생성된다.

버튼을 클릭한다.
3. [WM] 클러스터 포트선택
분리할 수 있는 포트 목록을 보여준다. 포트를 선택해 구성한다.

클러스터링에 포함되는 모든 서버는 반드시 같은 포트를 사용해야 한다.
서버 상태¶
클러스터에 소속된 모든 STON서버의 상태와 서비스 현황을 확인할 수 있다. 서버 목록을 구성하는 각 항목을 클릭하면 보다 상세한 정보를 확인하실 수 있다.

서버별 상태
가상호스트 상태¶
클러스터에서 서비스하는 모든 가상호스트의 MRTG를 종합하여 확인할 수 있다. 클러스터의 모든 가상호스트를 동시에 시작/중지할 수 있다. 가상호스트 목록을 구성하는 각 항목을 클릭하면 보다 상세한 정보를 확인하실 수 있다.

가상호스트 서비스별 상태
컨텐츠 제어¶
서비스 중인 컨텐츠를 열람/제어하거나 클린업을 수행할 수 있다. 클러스터 구성이 되어있다면 모든 STON의 컨텐츠를 동시에 열람하거나 제어할 수 있다.

Caching상태 확인

Purge등 API호출
4부. 고급기능¶
14장. 가상호스트 고급기법¶
이 장에서는 가상호스트를 활용하여 서비스를 유연하게 구성하는 여러 기법에 대해 설명한다.
가상호스트는 보통 원본(Domain 또는 IP목록)과 1:1로 구성되는 것이 기본이다. 하지만 상황에 따라 대표 가상호스트를 여러 하위 가상호스트로 분기하거나, 반대로 독립적인 여러 가상호스트를 하나의 서비스로 포장해야 하는 경우도 발생한다. 각 기능에 따라 클라이언트 통계 / Access 로그 의 정책이 다를 수 있음을 유의해야 한다.
URL 전처리¶
정규표현식 을 사용하여 요청된 URL을 변경한다. URL전처리가 설정되어 있다면 모든 클라이언 요청(HTTP 또는 File I/O)은 반드시 URL Rewriter를 거친다.

URL Rewriter를 통과해야 가상호스트에 갈 수 있다.
만약 URL Rewriter에 의해 접근하려는 Host이름이 변경되었다면 클라이언트 HTTP요청의 Host헤더가 변경된 것으로 간주한다. URL 전처리는 가상호스트 설정(vhosts.xml)에 설정한다. 대부분의 설정이 가상호스트에 종속되지만, URL전처리의 경우 클라이언트가 요청한 Host의 이름을 변경할 수 있으므로 가상호스트와 같은 레벨로 설정한다.
# vhosts.xml
<Vhosts>
<Vhost ...> ... </Vhost>
<Vhost ...> ... </Vhost>
<URLRewrite ...> ... </URLRewrite>
<URLRewrite ...> ... </URLRewrite>
</Vhosts>
멀티로 설정할 수 있으며 순차적으로 정규표현식 일치 여부를 비교한다.
# vhosts.xml - <Vhosts>
<URLRewrite AccessLog="Replace">
<Pattern>www.exmaple.com/([^/]+)/(.*)</Pattern>
<Replace>#1.exmaple.com/#2</Replace>
</URLRewrite>
<URLRewrite>
URL전처리를 설정한다.
AccessLog (기본: Replace)
속성은 Access로그에 기록될 URL을 설정한다.Replace
인 경우 변환 후 URL(/logo.jpg)을,Pattern
인 경우 변환 전 URL(/baseball/logo.jpg)을 Access로그에 기록한다.<Pattern>
매칭시킬 패턴을 설정한다. 한개의 패턴은 ( ) 괄호를 사용하여 표현된다.<Replace>
변환형식을 설정한다. 일치된 패턴에 대해서는 #1, #2와 같이 사용할 수 있다. #0는 요청 URL전체를 의미한다. 패턴은 최대 9개(#9)까지 지정할 수 있다.
처리량은 10장. 모니터링 & 통계 로 제공되며 URL 전처리 성공 으로도 확인할 수 있다. URL전처리는 Trimming , MP4 HLS 등 다른 기능들과 결합하여 표현을 간결하게 만든다.
# vhosts.xml - <Vhosts>
<URLRewrite>
<Pattern>example.com/([^/]+)/(.*)</Pattern>
<Replace>example.com/#1.php?id=#2</Replace>
</URLRewrite>
// Pattern : example.com/releasenotes/1.3.4
// Replace : example.com/releasenotes.php?id=1.3.4
<URLRewrite>
<Pattern>example.com/download/(.*)</Pattern>
<Replace>download.example.com/#1</Replace>
</URLRewrite>
// Pattern : example.com/download/1.3.4
// Replace : download.example.com/1.3.4
<URLRewrite>
<Pattern>example.com/img/(.*\.(jpg|png).*)</Pattern>
<Replace>example.com/#1/STON/composite/watermark1</Replace>
</URLRewrite>
// Pattern : example.com/img/image.jpg?date=20140326
// Replace : example.com/image.jpg?date=20140326/STON/composite/watermark1
<URLRewrite>
<Pattern>example.com/preview/(.*)\.(mp3|mp4|m4a)$</Pattern>
<Replace><![CDATA[example.com/#1.#2?&end=30&boost=10&bandwidth=2000&ratio=100]]></Replace>
</URLRewrite>
// Pattern : example.com/preview/audio.m4a
// Replace : example.com/audio.m4a?end=30&boost=10&bandwidth=2000&ratio=100
<URLRewrite>
<Pattern>example.com/(.*)\.mp4\.m3u8$</Pattern>
<Replace>example.com/#1.mp4/mp4hls/index.m3u8</Replace>
</URLRewrite>
// Pattern : example.com/video.mp4.m3u8
// Replace : example.com/video.mp4/mp4hls/index.m3u8
<URLRewrite>
<Pattern>example.com/(.*)_(.*)_(.*)</Pattern>
<Replace>example.com/#0/#1/#2/#3</Replace>
</URLRewrite>
// Pattern : example.com/video.mp4_10_20
// Replace : example.com/example.com/video.mp4_10_20/video.mp4/10/20
패턴표현에 XML의 5가지 특수문자( ” & ‘ < > )가 들어갈 경우 반드시 <![CDATA[ ... ]]>로 묶어주어야 올바르게 설정된다. 13장. WM (Web Management) 을 통해 설정할 때 모든 패턴은 CDATA로 처리된다.
Facade 가상호스트¶
<Alias>
는 가상호스트의 별명만을 추가하는 것이므로 통계와 로그가 분리되지 않는다.
가상호스트는 공유하지만 도메인에 따라 클라이언트 통계 와 Access 로그 를 분리하고 싶은 경우 Facade가상호스트를 설정한다.

facade는 통계와 로그만 수집한다.
# vhosts.xml - <Vhosts>
<Vhost Name="example.com">
...
</Vhost>
<Vhost Name="another.com" Status="facade:example.com">
...
</Vhost>
Status
속성의 값을 facade:
+ 가상호스트
로 설정한다.
예제의 경우 클라이언트 통계 와 Access 로그 는 example.com이 아닌 클라이언트가 요청한 도메인인 another.com으로 수집된다.
Sub-Path 지정¶
한 가상호스트에서 경로에 따라 다른 가상호스트가 처리하도록 설정할 수 있다.

통계/로그는 요청을 최종처리한 각각의 가상호스트에 기록된다.
# vhosts.xml - <Vhosts>
<Vhost Name="sports.com">
<Sub Status="Active">
<Path Vhost="baseball.com">/baseball/<Path>
<Path Vhost="football.com">/football/<Path>
<Path Vhost="photo.com">/*.jpg<Path>
</Sub>
</Vhost>
<Vhost Name="baseball.com" />
<Vhost Name="football.com" />
<Vhost Name="photo.com" />
<Sub>
경로나 패턴이 일치하면 해당 요청을 다른 가상호스트로 보낸다. 일치하지 않는 경우만 현재 가상호스트가 처리한다.Status (기본: Active)
Inactive인 경우 무시한다.<Path>
클라이언트가 요청한 URI와 경로가 일치하면Vhost
로 해당 요청을 보낸다. 값은 경로 또는 패턴만 가능하다.<Path Vhost="baseball.com">baseball<Path> <Path Vhost="photo.com">*.jpg<Path>
위와 같이 입력해도 각각 /baseball/과 /*.jpg로 인식된다.
예를 들어 클라이언트가 다음과 같이 요청했다면 해당 요청은 가상호스트 football.com이 처리한다.
GET /football/rank.html HTTP/1.1
Host: sports.com
Redirect 추적¶
원본서버에서 Redirect계열(301, 302, 303, 307)로 응답하는 경우 Location헤더를 추적하여 콘텐츠를 요청한다.
![]()
클라이언트는 Redirect여부를 모른다.
# server.xml - <Server><VHostDefault><OriginOptions>
# vhosts.xml - <Vhosts><Vhost><OriginOptions>
<RedirectionTrace>OFF</RedirectionTrace>
<RedirectionTrace>
OFF (기본)
3xx 응답으로 저장된다.ON
Location헤더에 명시된 주소에서 콘텐츠를 다운로드 한다. 형식에 맞지 않거나 Location헤더가 없는 경우에는 동작하지 않는다. 무한히 Redirect되는 경우를 방지하기 위하여 1회만 추적한다.
가상호스트 링크¶
콘텐츠가 여러 원본에 분산되어 있다면, 가상호스트 링크를 활용하여 콘텐츠가 통합되어 있는 것처럼 서비스가 가능하다. 특히 On-Premise에서 클라우드로 스토리지를 마이그레이션하거나, 스토리지의 용량, 비용 등의 이유로 콘텐츠가 분산되어 있는 환경에서 유용하다.

cloud.com에 없는 콘텐츠는 nas.com이 처리한다.
# vhosts.xml - <Vhosts><Vhost>
<VhostLink Condition="...">...</VhostLink>
<VhostLink>
요청을 위임할 가상호스트 이름. 콘텐츠에 대한 원본 응답이Condition
을 만족하면 지정된 가상호스트로 요청을 위임한다. 단 하나만 설정할 수 있다.Condition
HTTP 응답코드/패턴(1xx, 2xx, 3xx, 4xx, 5xx), fail(원본에서 캐싱하지 못한 경우)
클라이언트 요청이 다른 가상호스트로 위임되더라도 클라이언트 통계 와 Access 로그 는 클라이언트가 접근한 가상호스트에 기록된다.
주석
링크 관계에 있는 가상호스트 설정이 다를 경우 의도치 않게 동작할 수 있음을 주의한다. 가상호스트 링크가 A(단순 캐싱) -> B(이미지 압축)로 맺어져 있다면, A에서 처리된 이미지는 압축되지 않지만 B에서 처리된 이미지는 압축된다.
예를 들어 nas.com의 콘텐츠를 cloud.com으로 이전 중일 경우, cloud.com에 없는(=404 Not Found) 콘텐츠에 대해서만 nas.com으로 요청을 보낼 수 있다. 아래의 경우 요청이 nas.com에 의해 처리되더라도 클라이언트 통계 와 Access 로그 는 cloud.com에 기록된다.
# vhosts.xml - <Vhosts>
// cloud.com에 없는(=404 Not Found) 콘텐츠는 nas.com에서 서비스한다.
<Vhost Name="cloud.com">
<VhostLink Condition="404">nas.com</VhostLink>
</Vhost>
<Vhost Name="nas.com">
</Vhost>
Access 로그 의 vhostlink 필드를 통해 클라이언트 요청이 어느 가상호스트에서 처리되었는지 알 수 있다. “-” 는 요청이 링크되지 않았음을 의미하며 “nas.com” 은 해당 요청이 링크되어 nas.com에서 처리되었음을 의미한다.
#Fields: date time s-ip cs-method cs-uri-stem ...(중략)... vhostlink
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
링크가 여러 번 발생했다면 “+”를 구분자로 링크된 모든 가상호스트가 명시된다. 이 경우 가장 마지막에 위치한 가상호스트가 최종 요청을 처리한 가상호스트이다.
다음과 같이 여러 가상호스트를 다른 조건으로 링크할 수 있다.
# vhosts.xml - <Vhosts>
// 원본서버가 5xx로 응답했거나 캐싱하지 못했을 때(=fail) 해당 요청을 bar.com에게 위임한다.
<Vhost Name="foo.com">
<VhostLink Condition="5xx,fail">bar.com</VhostLink>
</Vhost>
// 원본서버가 4xx로 응답했을 때 해당 요청을 helloworld.com에게 위임한다.
<Vhost Name="bar.com">
<VhostLink Condition="4xx">helloworld.com</VhostLink>
</Vhost>
// 원본서버에서 403, 404 또는 5xx로 응답했을 때 해당 요청을 example.com에게 위임한다.
<Vhost Name="helloworld.com">
<VhostLink Condition="403,404,5xx">example.com</VhostLink>
</Vhost>
// 더 이상 위임하지 않는다.
<Vhost Name="example.com">
</Vhost>

억지스럽지만 가능하다.
위 예제의 경우 foo.com의 Access 로그 는 다음과 같다.
#Fields: date time s-ip cs-method cs-uri-stem ...(중략)... vhostlink
2016.11.24 16:52:24 220.134.10.5 GET /test.jpg ...(중략)... bar.com+helloworld.com+example.com
다음의 경우 링크는 즉시 중단된다.
- 대상 가상호스트가 존재하지 않는 경우 (foo.com -> ?)
- 자기 자신을 대상 가상호스트로 지정한 경우 (foo.com -> foo.com)
- 재귀링크(Recursive Link)가 발생한 경우 (foo.com -> bar.com -> foo.com)
15장. 접근제어¶
이 장에서는 원치않는 클라이언트 접근을 차단하는 방법에 대해 설명한다. 접근차단은 보통 ACL(Access Control List)에 차단목록(Black-list)을 작성하지만 설정편의상 허용목록(White-list)을 작성하기도 한다.
접근제어는 접속단계에서 수행하는 서버 접근제어와 가상호스트마다 설정하는 가상호스트 접근제어로 나뉜다. 수준별로 시점과 판단기준이 다르므로 효과적인 차단시점을 결정해야 한다. 접근제어의 동작은 모두 로그에 기록된다.
서버 접근제어¶
클라이언트가 서버에 접속하는 순간 IP정보를 통해 차단여부를 결정한다. 접속단계에서 처리되기 때문에 가장 확실하며 빠르다. 전역설정(server.xml)에 설정하며 가장 높은 우선순위를 가진다.
# server.xml - <Server><Host>
<ServiceAccess Default="Allow">
<Deny>192.168.7.9-255</Deny>
<Deny>192.168.8.10/255.255.255.0</Deny>
</ServiceAccess>
<ServiceAccess>
IP기반의 ACL을 설정한다. IP, IP Range, Bitmask, Subnet 이상 네 가지 형식을 지원한다. 순서를 인식하며 상위에 설정된 표현이 우선한다.Default (기본: Allow)
속성은 일치하는 조건이 없을 때 처리방법이다. 이 속성을Deny
로 설정하면 하위에<Allow>
로 허가할 조건들을 명시해주어야 한다.
차단된 IP는 Deny 로그 에 기록된다.
GeoIP¶
GeoIP를 사용하여 국가별로 접근을 차단할 수 있다. GeoIP Databases 중 Binary Databases를 GEOIP_MEMORY_CACHE and GEOIP_CHECK_CACHE 로 링크하여 실시간으로 변경내용을 반영한다.
# server.xml - <Server><Host>
<ServiceAccess GeoIP="/var/ston/geoip/">
<Deny>AP</Deny>
<Deny>GIN</Deny>
</ServiceAccess>
<ServiceAccess>
의 GeoIP
속성에 GeoIP Databases 경로를 설정한다.
국가코드는 ISO 3166-1 alpha-2 와
ISO 3166-1 alpha-3 를 지원한다.
주석
GeoIP는 파일명이 예약되어 있으므로 반드시 저장된 로컬경로를 입력하도록 설정한다. 또한 자동으로 변경이 반영되기 때문에 별도로 설정을 Reload하지 않아도 된다.
GeoIP가 설정되어 있다면 해당 디렉토리에 저장된 파일목록을 조회한다. 설정되어 있지 않다면 404 NOT FOUND로 응답한다.
http://127.0.0.1:10040/monitoring/geoiplist
결과는 JSON형식으로 제공된다.
{
"version": "2.0.0",
"method": "geoiplist",
"status": "OK",
"result":
{
"path" : "/usr/ston/geoip/",
"files" :
[
{
"file" : "GeoIP.dat",
"size" : 766255
},
{
"file" : "GeoLiteCity.dat",
"size" : 12826936
}
]
}
}
가상호스트 접근제어¶
가상호스트별로 접근을 제어한다. 클라이언트가 HTTP요청을 보냈을 때 차단여부를 결정한다. 왜냐하면 HTTP요청을 보내지 않는다면 가상호스트를 찾을 수 없기 때문이다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<AccessControl Default="Allow" DenialCode="401">OFF</AccessControl>
<AccessControl>
OFF (기본)
ACL이 활성화되지 않는다. 모든 클라이언트 요청을 허가한다.ON
ACL이 활성화된다. 차단된 요청에 대해서는DenialCode
속성에 설정된 응답코드로 응답한다.Default (기본: Allow)
속성이Allow
라면 ACL은 거부목록이 된다. 반대로Deny
라면 ACL은 허가목록이 된다.
Deny된 요청은 Access 로그 에 TCP_DENY로 기록된다.
가상호스트 ACL¶
모든 클라이언트 HTTP요청에 대하여 허용/거부/Redirect 여부를 판단한다. 각 조건마다 별도로 응답코드를 설정할 수도 있다. Redirect된 요청에 대해서는 302 Moved temporarily 로 응답한다. ACL은 /svc/{가상호스트 이름}/acl.txt에 설정한다.
# /svc/www.example.com/acl.txt
# 구분자는 콤마(,)이며 {조건},{키워드 = allow | deny | redirect} 순서로 표기한다.
# deny일 경우 키워드 뒤에 응답코드를 명시할 수 있다.
# 명시하지 않으면 ``<AccessControl>`` 의 ``DenialCode`` 를 사용한다.
# redirect일 경우 키워드 뒤에 이동시킬 URL을 명시한다. (Location헤더의 값으로 명시)
# n 개의 조건을 결합(AND)하기 위해서는 &를 사용한다.
$IP[192.168.1.1], allow
$IP[192.168.2.1-255]
$IP[192.168.3.0/24], deny
$IP[192.168.4.0/255.255.255.0]
$IP[AP] & !HEADER[referer], allow
$IP[GIN], redirect, /page/illegal_access.html
$HEADER[cookie: *ILLEGAL*], deny, 404
$HEADER[via: Apache]
$HEADER[x-custom-header]
$HEADER[referer:], redirect, http://another-site.com
!HEADER[referer] & !HEADER[user-agent] & !HEADER[host], deny
$URL[/source/public.zip], allow
$URL[/source/*]
/profile.zip, deny, 500
/secure/*.dat
조건은 IP, GeoIP, Header, URL 4가지로 설정이 가능하다.
- IP $IP[...]로 표기하며 IP, IP Range, Bitmask, Subnet 네 가지 형식을 지원한다.
- GeoIP $IP[...]로 표기하며 반드시 GeoIP설정이 되어 있어야 동작한다.
- Header $HEADER[Key : Value]로 표기한다. Value는 명확한 표현과 패턴을 인식한다. $HEADER[Key:]처럼 구분자는 있지만 Value가 빈 문자열이라면 요청 헤더의 값이 비어 있는 경우를 의미한다. $HEADER[Key]처럼 구분자 없이 Key만 명시되어 있다면 Key에 해당하는 헤더의 존재유무를 조건으로 판단한다.
- URL $URL[...]로 표기하며 생략이 가능합니다. 명확한 표현과 패턴을 인식합니다.
$는 “조건에 맞다면 ~ 한다”를 의미하지만 !는 “조건에 맞지 않는다면 ~ 한다”를 의미한다. 다음과 같이 부정조건으로 지원한다.
# 국가가 KOR이 아니라면 deny한다.
!IP[KOR], deny
# referer헤더가 존재하지 않는다면 deny한다.
!HEADER[referer], deny
# /secure/ 경로 하위가 아니라면 allow한다.
!URL[/secure/*], allow
Redirect 할 때 클라이언트가 요청한 URI가 필요할 수 있다.
이런 경우 #URI
키워드를 사용한다.
# referer헤더가 존재하지 않는다면 example.com에 요청 URI를 붙여서 Redirect한다.
# 클라이언트 요청은 /로 시작하기 때문에 #URI 앞에 /를 붙이지 않도록 주의한다.
!HEADER[referer], redirect, http://example.com#URI
16장. Bandwidth¶
이 장에서는 가상호스트별로 다양한 방식의 Bandwidth 제한(조절)방법에 대해 설명한다. 예전에는 Bandwidth가 일정수준을 넘지 못하도록 제한하는 것이 목적이었다. 이제는 효과적으로 Bandwidth를 조절하는 것으로 그 개념이 옮겨갔다. 나아가 콘텐츠를 실시간으로 분석해 각각에 최적화된 Bandwidth를 사용하도록 설정할 수 있다.
가상호스트 Bandwidth 제한¶
가상호스트의 최대 Bandwidth을 제한한다. 이는 가장 우선하는 물리적인 방법이다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<TrafficCap Session="0">0</TrafficCap>
<TrafficCap> (기본: 0 Mbps)
가상호스트의 최대 Bandwidth를 Mbps단위로 설정한다. 0으로 설정하면 Bandwidth을 제한하지 않는다.Session (기본: 0 Kbps)
속성은 클라이언트 세션별로 전송할 수 있는 최대 Bandwidth을 설정한다.
예를 들어 <TrafficCap>
을 50 (Mbps)로 설정했다면 50Mbps NIC를 설치한 것과 같은 효과를 낸다.
해당 가상호스트에 접근하는 모든 클라이언트 Bandwidth의 합은 50Mbps를 넘을 수 없다.
Session
은 다음과 같이 동작한다.
Session
이 설정되어 있더라도 모든 클라이언트 Bandwidth의 합은<TrafficCap>
을 넘을 수 없다.- Bandwidth Throttling 를 설정해도 클라이언트 세션별 최대 속도는
Session
을 넘을 수 없다.
Bandwidth Throttling¶
BT(Bandwidth Throttling)이란 (각 세션마다)클라이언트 전송 대역폭을 동적으로 조절하는 기능이다. 일반적인 미디어 파일의 내부는 다음과 같이 헤더, V(Video), A(Audio)로 구성되어 있다.

헤더는 BT의 대상이 아니다.
헤더는 재생시간이 길거나 Key Frame주기가 짧을수록 커진다. 그러므로 인식할 수 있는 미디어 파일이라면 원활한 재생을 위해 헤더는 대역폭 제한없이 전송한다. 다음 그림처럼 헤더가 완전히 전송된 뒤 BT가 시작된다.

동작 시나리오
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<BandwidthThrottling>
<Settings>
<Bandwidth Unit="kbps">1000</Bandwidth>
<Ratio>100</Ratio>
<Boost>5</Boost>
</Settings>
<Throttling>OFF</Throttling>
</BandwidthThrottling>
<BandwidthThrottling>
태그 하위에 기본동작을 설정한다.
<Settings>
기본 동작을 설정한다.
<Bandwidth> (기본: 1000 Kbps)
클라이언트 전송 대역폭을 설정한다.Unit
속성을 통해 기본 단위(kbps
,mbps
,bytes
,kb
,mb
)를 설정한다.<Ratio> (기본: 100 %)
<Bandwidth>
설정에 비율을 반영하여 대역폭을 설정한다.<Boost> (기본: 5 초)
일정 시간만큼의 데이터를 속도제한 없이 클라이언트에게 전송한다. 데이터의 양은<Boost>
X<Bandwidth>
X<Ratio>
공식으로 계산한다.
<Throttling>
OFF (기본)
BT를 적용하지 않는다.ON
조건목록과 일치하면 BT를 적용한다.
Bandwidth Throttling 조건목록¶
BT 조건목록을 설정한다. 조건목록과 일치해야 BT가 적용된다. 설정된 순서대로 조건과 일치하는지 검사한다. 전송 정책은 /svc/{가상호스트 이름}/throttling.txt 에 설정한다.
# /svc/www.example.com/throttling.txt
# 구분자는 콤마(,)이며 {조건},{Bandwidth},{Ratio},{Boost} 순서로 표기한다.
# {조건}을 제외한 모든 필드는 생략가능하다.
# 생략된 필드는 ``<Settings>`` 에 설정된 기본 값을 사용한다.
# 모든 조건표현은 acl.txt설정과 동일하다.
# {Bandwidth} 단위는 ``<Settings>`` ``<Bandwidth>`` 의 ``Unit`` 속성을 사용한다.
# 3초의 데이터를 속도 제한없이 전송한 후 3Mbps(3000Kbps = 2000Kbps X 150%)로 클라이언트에게 전송한다.
$IP[192.168.1.1], 2000, 150, 3
# bandwidth만 정의. 5(기본)초의 데이터를 속도 제한없이 전송한 후 800 Kbps로 클라이언트에게 전송한다.
!HEADER[referer], 800
# boost만 정의. 10초의 데이터를 속도 제한없이 전송한 후 1000 Kbps로 클라이언트에게 전송한다.
HEADER[cookie], , , 10
# 확장자가 m4a인 경우 BT를 적용하지 않는다.
$URL[*.m4a], no
미디어 파일(MP4, M4A, MP3)을 분석하면 Encoding Rate로부터 Bandwidth를 얻을 수 있다. 접근되는 콘텐츠의 확장자는 반드시 .mp4, .m4a, .mp3 중 하나여야 한다. 동적으로 Bandwidth를 추출하려면 다음과 같이 Bandwidth뒤에 x 를 붙인다.
# /vod/*.mp4 파일에 대한 접근이라면 bandwidth를 구한다. 구할 수 없다면 1000을 bandwidth로 사용한다.
$URL[/vod/*.mp4], 1000x, 120, 5
# user-agent헤더가 없다면 bandwidth를 구한다. 구할 수 없다면 500을 bandwidth로 사용한다.
!HEADER[user-agent], 500x
# /low_quality/* 파일에 대한 접근이라면 bandwidth를 구한다. 구할 수 없다면 기본 값을 bandwidth로 사용한다.
$URL[/low_quality/*], x, 200
QueryString 우선조건¶
약속된 QueryString을 사용하여 <Bandwidth>
, <Ratio>
, <Boost>
를 동적으로 설정한다.
이 설정은 BT조건보다 우선한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<BandwidthThrottling>
<Settings>
<Bandwidth Param="mybandwidth" Unit="mbps">2</Bandwidth>
<Ratio Param="myratio">100</Ratio>
<Boost Param="myboost">3</Boost>
</Settings>
<Throttling QueryString="ON">ON</Throttling>
</BandwidthThrottling>
<Bandwidth>
,<Ratio>
,<Boost>
의Param
각각의 의미에 맞게 QueryString 키를 설정한다.
<Throttling>
의QueryString
OFF (기본)
QueryString으로 조건을 재정의하지 않는다.ON
QueryString으로 조건을 재정의한다.
위와 같이 설정되어 있다면 다음과 같이 클라이언트가 요청한 URL에 따라 BT가 동적으로 설정된다.
# 10초의 데이터를 속도 제한없이 전송한 후 1.3Mbps(1mbps X 130%)로 클라이언트에게 전송한다.
http://www.winesoft.co.kr/video/sample.wmv?myboost=10&mybandwidth=1&myratio=130
반드시 모든 파라미터를 명시할 필요는 없다.
http://www.winesoft.co.kr/video/sample.wmv?myratio=150
위와 같이 일부 조건이 생략된 경우 나머지 조건(여기서는 bandwidth, boost)을 결정하기 위해 조건목록을 검색한다.
여기서도 적합한 조건을 찾지 못하는 경우 <Settings>
에 설정된 기본 값을 사용한다.
QueryString이 일부 존재하더라도 조건목록에서 미적용옵션(no)이 설정되어 있다면
BT는 적용되지 않는다.
QueryString을 사용하므로 자칫 QueryString 구분 과 혼동을 일으킬 소지가 있다.
QueryString 구분 이 ON
인 경우 클라이언트가 요청한 URL의 QueryString이
모두 인식되지만 BoostParam
, BandwidthParam
, RatioParam
은 제외된다.
GET /video.mp4?mybandwidth=2000&myratio=130&myboost=10
GET /video.mp4?tag=3277&myboost=10&date=20130726
예를 들어 위같은 입력은 BT를 결정하는데 쓰일 뿐 Caching-Key를 생성하거나 원본서버로 요청을 보낼 때는 제거된다. 즉 각각 다음과 같이 인식된다.
GET /video.mp4
GET /video.mp4?tag=3277&date=20130726
17장. 미디어¶
이 장에서는 미디어를 스마트하게 서비스하는 방법에 대해 설명한다. 클라이언트 환경과 서비스 다양화와 함께 콘텐츠를 다양한 형태로 가공하는 경우가 많다. 때문에 같은 콘텐츠지만 다양한 형태로 원본서버에 존재하게 된다. 이런 방식은 처리시간과 저장공간의 낭비로 이어질 뿐만 아니라 관리가 어렵다.
MP4/M4A 헤더위치 변경¶
보통 MP4포맷의 경우 인코딩 과정 중에는 헤더를 완성할 수 없기 때문에 완료 후 파일의 맨 뒤에 붙인다. 헤더를 앞으로 옮기려면 별도의 처리가 필요하다. 헤더가 뒤에 있다면 이를 지원하지 않는 플레이어에서 Pseudo-Streaming이 불가능하다. 헤더위치 변경을 통해 Pseudo-Streaming을 간편하게 지원할 수 있다.
헤더위치 변경은 전송단계에서만 발생할 뿐 원본의 형태를 변경하지 않는다. 별도의 저장공간을 사용하지도 않는다.
# server.xml - <Server><VHostDefault><Media>
# vhosts.xml - <Vhosts><Vhost><Media>
<UpfrontMP4Header>OFF</UpfrontMP4Header>
<UpfrontM4AHeader>OFF</UpfrontM4AHeader>
<UpfrontMP4Header>
OFF (기본)
아무 것도 하지 않는다.ON
확장자가 .mp4이고 헤더가 뒤에 있다면 헤더를 앞으로 옮겨서 전송한다.
<UpfrontM4AHeader>
OFF (기본)
아무 것도 하지 않는다.ON
확장자가 .m4a이고 헤더가 뒤에 있다면 헤더를 앞으로 옮겨서 전송한다.
처음 요청되는 콘텐츠의 헤더를 앞으로 옮겨야 한다면 헤더를 옮기기위해 필요한 부분을 우선적으로 다운로드 받는다. 아주 영리할뿐만 아니라 빠르게 동작한다. 커튼 뒤의 복잡한 과정과는 상관없이, 클라이언트는 원래부터 헤더가 앞에 있는 온전한 파일을 서비스 받는다.
주석
분석할 수 없거나 깨진 파일이라면 원본형태 그대로 서비스된다.
Trimming¶
시간 값을 기준으로 원하는 구간을 추출한다. Trimming은 전송단계에서만 발생할 뿐 원본의 형태를 변경하지 않는다. 별도의 저장공간을 사용하지 않는다.
# server.xml - <Server><VHostDefault><Media>
# vhosts.xml - <Vhosts><Vhost><Media>
<MP4Trimming StartParam="start" EndParam="end" AllTracks="off">OFF</MP4Trimming>
<M4ATrimming StartParam="start" EndParam="end" AllTracks="off">OFF</M4ATrimming>
<MP3Trimming StartParam="start" EndParam="end">OFF</MP3Trimming>
<MP4Trimming>
<MP3Trimming>
<M4ATrimming>
OFF (기본)
아무 것도 하지 않는다.ON
확장자(.mp4, .mp3, .m4a)가 일치하면 원하는 구간만큼 서비스하도록 Trimming한다. Trimming구간은StartParam
속성과EndParam
으로 설정한다.AllTracks
속성OFF (기본)
Audio/Video 트랙만 Trimming한다. (Mod-H264 방식)ON
모든 트랙을 Trimming한다. 사용 전 반드시 플레이어 호환성을 확인해야 한다.
파라미터는 클라이언트 QueryString을 통해 입력받는다. 예를 들어 10분 분량의 동영상(/video.mp4)을 특정 구간만 Trimming하고 싶다면 QueryString에 원하는 시점(단위: 초)을 명시한다.
http://vod.wineosoft.co.kr/video.mp4 // 10분 : 전체 동영상
http://vod.wineosoft.co.kr/video.mp4?end=60 // 1분 : 처음부터 60초까지
http://vod.wineosoft.co.kr/video.mp4?start=120 // 8분 : 2분(120초)부터 끝까지
http://vod.wineosoft.co.kr/video.mp4?start=3&end=13 // 10초 : 3초부터 13초까지
StartParam
값이 EndParam
값보다 클 경우 구간이 지정되지 않은 것으로 판단한다.
이 기능은 HTTP Pseudo-Streaming으로 구현된 동영상 플레이어의 Skip기능을 위해서 개발되었다.
그러므로 Range요청을 처리하는 것처럼 파일을 Offset기반으로 자르지 않고 올바르게 재생될 수 있도록 키프레임과 시간을 인지하여 구간을 추출한다.
클라이언트에게 전달되는 파일은 다음 그림처럼 MP4헤더가 재생성된 완전한 형태의 MP4파일이다.

완전한 형태의 파일이 제공된다.
추출된 구간은 별도의 파일로 인식되기 때문에 200 OK로 응답된다. 그러므로 다음과 같이 Range헤더가 명시된 경우 추출된 파일로부터 Range를 계산하여 206 Particial Content 로 응답한다.

일반적인 Range요청처럼 처리된다.
구간추출 파라미터가 QueryString 표현을 사용하기 때문에 자칫 QueryString 구분 과 헷갈릴 수 있다.
<ApplyQueryString>
설정이 ON
인 경우 클라이언트가 요청한 URL의 QueryString이 모두 인식되지만 StartParam
과 EndParam
은 제거된다.
GET /video.mp4?start=30&end=100
GET /video.mp4?tag=3277&start=30&end=100&date=20130726
예를 들어 위와 같이 StartParam
이 start 로 EndParam
이 end 로 입력된 경우
이 값들은 구간을 추출하는데 쓰일 뿐 Caching-Key를 생성하거나 원본서버로 요청을 보낼 때는 제거된다.
각각 다음과 같이 인식된다.
GET /video.mp4
GET /video.mp4?tag=3277&date=20130726
또한 QueryString파라미터는 확장모듈이나 CDN솔루션에 따라 달라질 수 있다.

JW Player에서 제공하고 있는 Module/CDN별 참고자료
이외의 nginx의 ngx_http_mp4_module 과, lighttpd의 Mod-H264-Streaming-Testing-Version2 에서도 모두 start 를 QueryString으로 사용하고 있다.
Multi-Trimming¶
시간 값을 기준으로 복수로 지정된 구간을 하나의 영상으로 추출한다.

/video.mp4?trimming=0-30,210-270,525-555
구간 지정방법만 다를뿐 동작방식은 Trimming 과 동일하다.
# server.xml - <Server><VHostDefault><Media>
# vhosts.xml - <Vhosts><Vhost><Media>
<MP4Trimming MultiParam="trimming" MaxRatio="50">OFF</MP4Trimming>
<M4ATrimming MultiParam="trimming">OFF</M4ATrimming>
<MP4Trimming>
<M4ATrimming>
MultiParam (기본: "trimming")
설정된 이름을 QueryString Key로 사용하여 추출 구간을 지정한다. 하나의 구간은 “시작시간 - 종료시간” 으로 표기하며 각 구간은 콤마(,)로 연결한다.MaxRatio (기본: 50%)
Multi-Trimming된 영상은 원본보다MaxRatio (최대 100%)
비율만큼까지 커질 수 있다.MaxRatio
를 넘어가는 구간은 무시된다.
예를 들어 다음과 같이 호출하면 3분짜리 영상이 생성된다.
http://example.com/video.mp4?trimming=10-70,560-620,1245-1305
같은 영상을 반복하거나 앞 뒤가 바뀐 영상을 만들 수도 있다.
http://example.com/video.mp4?trimming=17-20,17-20,17-20,17-20
http://example.com/video.mp4?trimming=1000-1200,500-623,1900-2000
http://example.com/video.mp4?trimming=600-,400-600
구간 값을 지정하지 않은 경우 맨 앞 또는 맨 뒤를 의미한다.
주석
Multi-Trimming 은 Trimming 보다 우선한다. QueryString에 Multi-Trimming 키가 명시되어 있다면 Trimming 키는 무시된다.
MP4 HLS¶
MP4파일을 HLS(HTTP Live Streaming)로 서비스한다. 원본서버는 더 이상 HLS서비스를 위해 파일을 분할저장할 필요가 없다. MP4파일 헤더의 위치에 상관없이 다운로드와 동시에 실시간으로 .m3u8/.ts파일 변환 후 서비스한다.
주석
MP4HLS는 Elementary Stream(Video 또는 Audio)을 변환하는 트랜스코딩(Transcoding)이 아니다. 그러므로 HLS에 적합한 형식으로 인코딩된 MP4파일에 한해서 원활한 단말 재생이 가능하다. 인코딩이 적합하지 않을 경우 화면이나 깨지거나 소리가 재생되지 않을 수 있다. 현재(2014.2.20) Apple에서 밝히고 있는 Video/Audio 인코딩 규격은 다음과 같다.
What are the specifics of the video and audio formats supported? Although the protocol specification does not limit the video and audio formats, the current Apple implementation supports the following formats:
[Video] H.264 Baseline Level 3.0, Baseline Level 3.1, Main Level 3.1, and High Profile Level 4.1.
[Audio] HE-AAC or AAC-LC up to 48 kHz, stereo audio MP3 (MPEG-1 Audio Layer 3) 8 kHz to 48 kHz, stereo audio AC-3 (for Apple TV, in pass-through mode only)
Note: iPad, iPhone 3G, and iPod touch (2nd generation and later) support H.264 Baseline 3.1. If your app runs on older versions of iPhone or iPod touch, however, you should use H.264 Baseline 3.0 for compatibility. If your content is intended solely for iPad, Apple TV, iPhone 4 and later, and Mac OS X computers, you should use Main Level 3.1.
기존 방식의 경우 Pseudo-Streaming과 HLS를 위해 다음과 같이 원본파일이 각각 존재해야 한다. 이런 경우 STON 역시 원본 파일을 그대로 복제하여 고객에게 서비스한다. 하지만 재생시간이 길수록 파생파일은 많아지며 관리의 어려움은 증가한다.

수고가 많은 HLS
<MP4HLS>
는 원본파일로부터 HLS서비스에 필요한 파일을 동적으로 생성한다.

똑똑한 HLS
모든 .m3u8/.ts파일은 원본파일에서 파생되며 별도의 저장공간을 소비하지 않는다. 서비스 즉시 메모리에 임시적으로 생성되며 서비스되지 않을 때 자동으로 없어진다.
# server.xml - <Server><VHostDefault><Media>
# vhosts.xml - <Vhosts><Vhost><Media>
<MP4HLS Status="Inactive" Keyword="mp4hls">
<Index Ver="3" Alternates="off">index.m3u8</Index>
<Sequence>0</Sequence>
<Duration>10</Duration>
<AlternatesName>playlist.m3u8</AlternatesName>
</MP4HLS>
<MP4HLS>
Status (기본: Inactive)
값이Active
일 때만 활성화된다.Keyword (기본: mp4hls)
HLS 서비스 키워드
<Index> (기본: index.m3u8)
HLS 인덱스(.m3u8) 파일명Ver (기본 3)
인덱스 파일 버전. 3인 경우#EXT-X-VERSION:3
헤더가 명시되며#EXTINF
의 시간 값이 소수점 3째 자리까지 표시된다. 1인 경우#EXT-X-VERSION
헤더가 없으며,#EXTINF
의 시간 값이 정수(반올림)로 표시된다.Alternates (기본: OFF)
Stream Alternates 사용여부.OFF.
<Index>
에서 TS목록을 서비스한다.ON.
<AlternatesName>
에서 TS목록을 서비스한다.
<Sequence> (기본: 0)
.ts 파일의 시작 번호. 이 수를 기준으로 순차적으로 증가한다.<Duration> (기본: 10초)
MP4를 HLS로 분할하는 기준 시간(초). 분할의 기준은 Video/Audio의 KeyFrame이다. KeyFrame은 들쭉날쭉할 수 있으므로 정확히 분할되지 않는다. 만약 10초로 분할하려는데 KeyFrame이 9초와 12초에 있다면 가까운 값(9초)을 선택한다.<AlternatesName> (기본: playlist.m3u8)
Stream Alternates 파일명.http://www.example.com/video.mp4/mp4hls/playlist.m3u8
서비스 주소가 다음과 같다면 해당 주소로 Pseudo-Streaming을 진행할 수 있다.
http://www.example.com/video.mp4
가상호스트는 <MP4HLS>
에 정의된 Keyword
문자열을 인식함으로써 HLS서비스를 진행한다.
다음 URL이 호출되면 /video.mp4로부터 index.m3u8파일을 생성한다.
http://www.example.com/video.mp4/mp4hls/index.m3u8
Alternates
속성이 ON이라면 <Index>
파일은 <AlternatesName>
파일을 서비스한다.
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=200000,RESOLUTION=720x480
/video.mp4/mp4hls/playlist.m3u8
#EXT-X-STREAM-INF
의 Bandwidth와 Resolution은 영상을 분석하여 동적으로 제공한다.
주석
Stream Alternates를 제공하긴 하지만 현재 버전에서 index.m3u8는 항상 하나의 서브 인덱스 파일(playlist.m3u8)만을 제공한다. 캐시 입장에서는 video_1080.mp4와 video_720.mp4가 (인코딩 옵션만 다른) 같은 영상인지 알 수 없기 때문이다.
최종적으로 생성된 .ts 목록(버전 3)은 다음과 같다.
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:11.637,
/video.mp4/mp4hls/0.ts
#EXTINF:10.092,
/video.mp4/mp4hls/1.ts
#EXTINF:10.112,
/video.mp4/mp4hls/2.ts
... (중략)...
#EXTINF:10.847,
/video.mp4/mp4hls/161.ts
#EXTINF:9.078,
/video.mp4/mp4hls/162.ts
#EXT-X-ENDLIST
분할에는 3가지 정책이 있다.
- KeyFrame 간격보다
<Duration>
설정이 큰 경우 KeyFrame이 3초,<Duration>
이 20초라면 20초를 넘지 않는 KeyFrame의 배수인 18초로 분할된다. - KeyFrame 간격과
<Duration>
이 비슷한 경우 KeyFrame이 9초,<Duration>
이 10초라면 10초를 넘지 않는 KeyFrame의 배수인 9초로 분할된다. - KeyFrame 간격이
<Duration>
설정보다 큰 경우 KeyFrame단위로 분할된다.
다음 클라이언트 요청에 대해 STON이 어떻게 동작하는지 이해해보자.
GET /video.mp4/mp4hls/99.ts HTTP/1.1
Range: bytes=0-512000
Host: www.wineosft.com
STON
최초 로딩. (아무 것도 캐싱되어 있지 않음.)Client
HTTP Range 요청. (100번째 파일의 최초 500KB 요청)STON
/video.mp4 파일 캐싱객체 생성.STON
/video.mp4 파일 분석을 위해 필요한 부분만을 원본서버에서 다운로드STON
100번째(99.ts)파일 서비스를 위해 필요한 부분만을 원본서버에서 다운로드STON
100번째(99.ts)파일 생성 후 Range 서비스STON
서비스가 완료되면 99.ts파일 파괴
주석
MP4Trimming
기능이 ON
이라면 Trimming된 MP4를 HLS로 변환할 수 있다. (HLS영상을 Trimming할 수 없다. HLS는 MP4가 아니라 MPEG2TS 임에 주의하자.)
영상을 Trimming한 뒤, HLS로 변환하기 때문에 다음과 같이 표현하는 것이 자연스럽다.
/video.mp4?start=0&end=60/mp4hls/index.m3u8
동작에는 문제가 없지만 QueryString을 맨 뒤에 붙이는 HTTP 규격에 어긋난다. 이를 보완하기 위해 다음과 같은 표현해도 동작은 동일하다.
/video.mp4/mp4hls/index.m3u8?start=0&end=60
/video.mp4?start=0/mp4hls/index.m3u8?end=60
MP3 HLS¶
MP3파일을 HLS(HTTP Live Streaming)로 서비스한다.
# server.xml - <Server><VHostDefault><Media>
# vhosts.xml - <Vhosts><Vhost><Media>
<MP3HLS Status="Inactive" Keyword="mp3hls">
<Index Ver="3" Alternates="off">index.m3u8</Index>
<Sequence>0</Sequence>
<Duration>10</Duration>
<AlternatesName>playlist.m3u8</AlternatesName>
</MP3HLS>
모든 설정과 동작방식이 MP4 HLS 와 동일하다.
DIMS¶
DIMS(Dynamic Image Management System)는 원본이미지를 다양한 형태로 가공하는 기능이다. mod_dims 를 기반으로 확장한 형태이다. 가공형태는 모두 7가지(optimize, crop, thumbnail, resize, reformat, quality, composite)이며 이를 조합한 복합가공이 가능하다.

다양한 동적 이미지 가공
이미지는 동적으로 생성되며 원본 이미지 URL뒤에 약속된 키워드와 가공옵션을 붙여서 호출한다. 가공된 이미지는 캐싱되어 원본서버 이미지가 바뀌지 않는 이상 다시 가공되지 않는다.
예를 들어 원본 파일이 /img.jpg라면 다음과 같은 형식으로 이미지를 가공할 수 있다. (“12AB”는 약속된 Keyword이다.)
http://image.example.com/img.jpg // 원본 이미지
http://image.example.com/img.jpg/12AB/optimize
http://image.example.com/img.jpg/12AB/resize/500x500/
http://image.example.com/img.jpg/12AB/crop/400x400/
http://image.example.com/img.jpg/12AB/composite/watermark1/
<Dims>
는 별도로 설정하지 않으면 모두 비활성화되어 있다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<Dims Status="Active" Keyword="dims" MaxSourceSize="10" OnFailure="message" />
<Dims>
Status
DIMS활성화 (Active
또는Inactive
)Keyword
원본과 DIMS를 구분하는 키워드MaxSourceSize (기본: 10MB)
변환을 허용할 최대 원본 이미지 크기 (단위: MB)OnFailure
이미지 변환실패 시 동작방식message (기본)
500 Internal Error로 응답한다. 본문에는 구체적인 실패 이유를 명시한다.The original file was not successfully downloaded.
원본이미지를 완전하게 다운로드 하지 못했다.The original file size is too large.
원본이미지 크기가MaxSourceSize
를 넘어 변환하지 못했다.The original file loading failed.
원본 이미지 데이터를 불러오지 못했다.Image converting failed or invalid DIMS command.
잘못된 명령어 또는 지원되지 않는 이미지등으로 인해 변환하지 못했다.
redirect
원본 이미지 주소로 302 Redirect한다.
최적화¶
최적화란 이미지 품질을 저하시키지 않으면서 이미지를 압축하는 과정이다. JPEG, JPEG-2000, Loseless-JPEG 이미지만 지원이 가능하다. 이미 다른 도구등을 통해 최적화된 이미지는 더 이상 최적화되지 않는다.
http://image.example.com/img.jpg/dims/optimize
최적화는 키워드 이외 별도의 옵션을 가지지 않는다. 그러므로 다른 변환조건과 조합할 때 맨 뒤에 명시하는 편이 바람직하다.
http://image.example.com/img.jpg/dims/resize/100x100/optimize
다른 모든 DIMS기능이 시스템 자원을 많이 사용하지만 그 중에서도 최적화가 가장 무거운 작업이다. 다음은 HitRatio가 0%인 상태에서 이미지 크기별 성능 테스트 결과이다.
OS
CentOS 6.2 (Linux version 2.6.32-220.el6.x86_64 (mockbuild@c6b18n3.bsys.dev.centos.org) (gcc version 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC) ) #1 SMP Tue Dec 6 19:48:22 GMT 2011)CPU
Intel(R) Xeon(R) CPU E3-1230 v3 @ 3.30GHz (8 processors)RAM
16GBHDD
SMC2108 SAS 275GB X 3EA
크기 | 처리량 | 응답속도(ms) | 클라이언트 트래픽(Mbps) | 원본 트래픽(Mbps) | 트래픽 절감률(%) |
---|---|---|---|---|---|
16KB | 720 | 19.32 | 46.32 | 92.62 | 49.99 |
32KB | 680 | 20.68 | 86.42 | 165.08 | 47.65 |
64KB | 285 | 50.16 | 80.67 | 150.96 | 46.56 |
128KB | 274 | 57.80 | 164.35 | 276.52 | 40.56 |
256KB | 210 | 80.74 | 99.42 | 432.35 | 77.00 |
512KB | 113 | 156.18 | 160.54 | 436.04 | 63.18 |
1MB | 20 | 981.07 | 90.62 | 179.88 | 49.62 |
약 50%내외의 트래픽 절감률이 있으므로 매우 효과적이다. 다시 한번 말하지만 최적화는 매우 무거운 작업이다. 표를 통해 알 수 있듯이 이미지 크기가 가장 큰 변수가 된다.
때문에 충분한 고려없이 서비스에 적용했다가는 큰 낭패를 볼 수 있다. 적당한 Request hit ratio 가 있는 상황이 바람직하나, 그렇지 않다면 서비스 규모에 맞게 물리적인 CPU자원을 충분히 확보해야 한다.
잘라내기¶
좌상단을 기준으로 원하는 영역만큼 이미지를 잘라낸다. 영역은 widthxheight{+-}x{+-}y{%} 로 표현한다. 다음은 좌상단 x=20, y=30을 기준으로 width=100, height=200만큼 잘라내는 예제다.
http://image.example.com/img.jpg/dims/crop/100x200+20+30/
Thumbnail 생성¶
Thumbnail 을 생성한다. 크기와 옵션은 widthxheight{%} {@} {!} {<} {>} 로 표현한다. 기본적으로 이미지의 가로와 세로는 최대값을 사용한다. 이미지를 확대 또는 축소하여도 가로 세로 비율은 유지된다. 정확하게 지정한 크기로 이미지를 조절할 때는 크기 뒤에 느낌표(!)를 추가한다. 640X480! 라는 표현은 정확하게 640x480 크기의 Thumbnail을 생성한다는 뜻이다. 만약 가로 또는 세로 크기만 지정된 경우, 생략된 값은 가로/세로 비율에 의해 자동결정 된다.
예를 들어 /thumbnail/100/ 은 가로 크기에 맞추어 세로 크기가 결정되며 /thumbnail/x200/ 은 세로 크기에 맞추어 가로 크기가 결정된다. 가로/세로 크기를 이미지의 크기에 맞추어 백분율(%)로 표현할 수 있다. 이미지 크기를 늘리려면, 100 보다 큰 값(예 : 125 %)을 사용한다. 이미지 크기를 줄이려면 100 미만의 비율을 사용한다. URL Encoding규칙에 따라 %문자가 %25로 인코딩 됨을 명심해야 한다.
예를 들어 50%라는 표현은 50%25로 인코딩 된다. 다음은 width=78, height=110크기의 Thumbnail을 생성하는 예제다.
http://image.example.com/img.jpg/dims/thumbnail/78x110/
Resizing¶
이미지 크기를 변경한다. 크기는 width x height 로 표현한다. 이미지는 변경되어도 비율은 유지된다. 다음은 원본 이미지를 width=200, height=200크기로 변경하는 예제다.
http://image.example.com/img.jpg/dims/resize/200x200/
Format 변경¶
이미지 포맷을 변경한다. 지원되는 포맷은 “png”, “jpg”, “gif” 이다. 다음은 JPG를 PNG로 변환하는 예제다.
http://image.example.com/img.jpg/dims/format/png/
품질 변경¶
이미지 품질을 조절한다. 이 기능은 전송되는 이미지 용량을 줄일 수 있어서 효과적이다. 유효 범위는 0부터 100까지다. 다음은 이미지 품질을 25%로 조절하는 예제다.
http://image.example.com/img.jpg/dims/quality/25/
합성¶
두 이미지를 합성한다. 앞서 설명한 기능과는 다르게 합성조건은 미리 설정되어 있어야 한다. 주로 워터마크 효과를 내기 위해 사용된다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<Dims Status="Active" Keyword="dims" port="8500">
<Composite Name="water1" File="/img/small.jpg" />
<Composite Name="water2" File="/img/medium.jpg" Gravity="se" Geometry="+0+0" Dissolve="50" />
<Composite Name="water_ratio" File="/img/wmark_s.png" Gravity="s" Geometry="+0+15%" Dissolve="100" />
</Dims>
<Composite>
이미지 합성조건을 설정한다. 속성에 의해 정해지며 별도의 값을 가지지 않는다.
Name
호출될 이름을 지정한다. ‘/’문자는 입력할 수 없다. URL의 “/composite/” 뒤에 위치합니다.File
합성할 이미지파일 경로를 지정한다.Gravity (기본: c)
합성할 위치는 좌측상단부터 9가지의 포인트(nw, n, ne, w, c, e, sw, s, se)가 존재합니다.Gavity 기준점
Geometry (기본: +0+0)
Gravity
기준으로 합성할 이미지 위치를 설정한다. {+-}x{+-}y. 붉은색 원은 Gravity속성에 따라 +0+0이 의미하는 기준점으로 +x+y의 값이 커질수록 이미지 안쪽으로 배치된다. 초록색 화살표는 +x, 보라색 화살표는 +y가 증가하는 방향이다. -x-y를 사용하면 대상 이미지의 바깥에 위치하게 되어 결과 이미지에서는 보여지지 않는다. 이 속성은 다소 복잡해 보이지만 이미지 크기를 자동으로 계산하여 배치하므로 일관된 결과물을 얻을 수 있어서 효과적이다. 또한 +x%+y% 처럼 %옵션을 주어 비율로 배치할 수도 있다.Dissolve (기본: 50)
합성할 이미지의 투명도(0~100).
<Composite>
을 설정했다면 Name
속성을 사용하여 이미지를 합성할 수 있다.
http://image.example.com/img.jpg/dims/composite/water1/
원본이미지 조건판단¶
원본 이미지 조건에 따라 동적으로 가공 옵션을 다르게 적용할 수 있다.
예를 들어 1024 X 768 이하의 이미지는 품질을 50%로 떨어트리고 그 이상의
이미지는 1024 X 768로 크기변환을 하려면 다음과 같이 <ByOriginal>
을 설정한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<Dims Status="Active" Keyword="dims" port="8500">
<ByOriginal Name="size1">
<Condition Width="1024" Height="768">/quality/50/</Condition>
<Condition>/resize/1024x768/</Condition>
</ByOriginal>
</Dims>
<ByOriginal>
Name
속성으로 호출한다. 하위에 다양한 조건의<Condition>
을 설정한다.<Condition>
조건에 만족하는 경우 설정된 변환을 수행한다.Width
가로 길이가 설정 값보다 작으면 적용된다.Height
세로 길이가 설정 값보다 작으면 적용된다.
조건을 설정하지 않으면 원본 이미지 크기에 상관없이 변환된다.
<Condition>
은 명시된 순서대로 적용된다.
그러므로 작은 이미지 조건을 먼저 배치해야 한다.
다음과 같이 호출한다.
http://image.example.com/img.jpg/dims/byoriginal/size1/
또 다른 예로 이미지 크기에 따라 다른 <Composite>
조건을 줄 수 있다.
이런 경우 다음과 같이 사전에 정의된 <Composite>
의 Name
으로 설정한다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<Dims Status="Active" Keyword="dims" port="8500">
<Composite Name="water1" File="/img/small.jpg" />
<Composite Name="water2" File="/img/medium.jpg" Gravity="se" Geometry="+0+0" Dissolve="50" />
<Composite Name="water3" File="/img/big.jpg" Gravity="se" Geometry="+10+10" Dissolve="50" />
<ByOriginal Name="size_water">
<Condition Width="400">/composite/water1/</Condition>
<Condition Width="800">/composite/water2/</Condition>
<Condition>/composite/water3/</Condition>
</ByOriginal>
</Dims>
다음과 같이 호출하면 원본 이미지 크기에 따라 합성이 적용된다.
http://image.example.com/img.jpg/dims/byoriginal/size_water/
Animated GIF¶
Animated GIF에 대해서도 모든 DIMS변환이 동일하게 적용된다. 처리 순서는 다음과 같다.
- Animated GIF를 낱개의 이미지들로 분해한다.
- 각각의 이미지를 변환한다.
- 변환된 이미지를 Animated GIF로 결합한다.
결합된 이미지가 많을수록 처리비용이 높아 서비스 품질이 저하될 수 있다. 이런 경우 첫 번째 이미지에 대해서만 변환하도록 설정하면 처리 비용을 낮출 수 있다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<Dims FirstFrameOnly="OFF" />
FirstFrameOnly (기본: OFF)
ON인 경우 Animated GIF의 첫 장면만 변환한다.
다음과 같이 URL을 호출할 때 FirstFrameOnly
옵션을 명시적으로 지정할 수 있다.
http://image.example.com/img.jpg/dims/firstframeonly/on/resize/200x200/
http://image.example.com/img.jpg/dims/firstframeonly/off/resize/200x200/
위와 같이 URL에 명시적으로 지정되어 있는 경우 설정보다 우선한다.
기타¶
이상의 기본기능을 결합하여 복합적인 이미지 가공을 할 수 있다. 예를 들어 Thumbnail생성(78x110), 포맷을 JPG에서 PNG로 변환, 품질 50% 이상의 옵션을 한번의 호출로 실행할 수 있다.
http://image.example.com/img.jpg/dims/thumbnail/78x110/format/png/quality/50/
DIMS는 URL을 이용하여 이미지 가공이 이루어진다. 그러므로 URL에 영향을 주는 다른 옵션들 때문에 원하지 않는 결과가 얻어지지 않도록 주의해야 한다.
QueryString 구분 이
OFF
라면 키워드 이전의 QueryString이 무시된다.http://image.example.com/img.jpg?session=5234&type=37/dims/resize/200x200/
위와 같은 호출에 이 설정이
ON
이라면 입력된 URL 그대로 인식되지만 OFF라면 다음과 같이 인식된다.http://image.example.com/img.jpg/dims/resize/200x200/
대소문자 구분 이
OFF
라면 모든 URL을 소문자로 변환하여 처리한다. 그러므로 DIMS 키워드에 대문자가 포함되었다면 키워드를 인식하지 못한다. 항상 키워드는 소문자로 사용하는 것이 좋다.
18장. File System¶
이 장에서는 STON을 로컬 디스크처럼 사용하는 방법에 대해 설명한다. STON은 FUSE 를 기반으로 Linux VFS(Virtual File System)에 Mount된다. Mount된 경로의 모든 파일은 접근되는 순간 Caching되지만 다른 프로세스는 이 사실을 알지 못한다. Caching기능이 탑재된 ReadOnly 디스크 로 이해해도 좋다.

구조상 File I/O 함수 호출을 Linux Kernel이 STON에게 직접 전달하는 과정에 어떠한 요소(물리적 파일 I/O 또는 Socket통신 등)도 개입하지 않는다. 이런 구조는 아주 높은 성능을 가능케 한다. STON의 메모리 Caching을 통해 물리적 디스크 접근보다 뛰어난 성능을 기대할 수 있다.
Mount하기¶
전역설정(server.xml)에 설정한다.
# server.xml - <Server><Cache>
<FileSystem Mount="/cachefs" DotDir="OFF" Separator="^">OFF</FileSystem>
<FileSystem>
OFF (기본)
아무 것도 하지 않는다.ON
STON을Mount
속성의 경로에 Mount한다.
기존 HTTP 구조를 그대로 유지한 채 Cache 모듈에 접근하는 방식(File System)이 추가된 구조로 개발되었다. 그러므로 어느 쪽으로부터의 접근이든 Caching은 처음 한번만 이루어지며 HTTP 또는 File I/O로 서비스된다. FileSystem은 Cache모듈에 접근하는 새로운 다리를 하나 더 놓은 것다.

HTTP와 File I/O가 Cache모듈을 공유한다.
원본서버의 콘텐츠를 HTTP 뿐만 아니라 File I/O로 양쪽에서 접근할 수 있다. 이를 활용하면 로컬파일에 기반한 솔루션들의 가용성을 더 높일 수 있다.

어떤 서버라도 OK
현재 STON File System이 지원하는 함수 목록은 다음과 같다.
FUSE | C | LINUX |
---|---|---|
open | fopen | open |
release | fclose | close |
read | fseek, fread | seek, read |
getattr | fstat | stat |
unlink | remove | unlink |
File I/O는 내부적으로 여러 단계를 거친다. 각 단계에 대한 이해가 바탕이 되어야 최고의 성능을 얻을 수 있다.
가상호스트 찾기¶
첫 번째 과정은 접근하려는 가상호스트를 찾는 것이다. HTTP 요청에는 다음과 같이 Host헤더가 명시되어 있어 가상호스트를 쉽게 찾을 수 있다.
GET /ston.jpg HTTP/1.1
host: example.com
File System에서는 첫 번째 경로로 이 문제를 해결한다. 예를 들어 STON이 /cachefs 라는 경로에 Mount되어 있다면 로컬파일에 접근하기 위해서는 다음 경로를 사용해야 한다.
/cachefs/example.com/ston.jpg
찾기 도 동일하게 동작한다.
example.com의 <Alias>
로 *.example.com이 지정되어 있다면 다음 접근은 모두 같은 파일을 가리킨다.
/cachefs/example.com/ston.jpg
/cachefs/img.example.com/ston.jpg
/cachefs/example.example.com/ston.jpg
예를들어 Apache에서 example.com을 연동하기 위해서는 DocumentRoot를 /cachefs/example.com/로 설정해야 한다.
파일/디렉토리¶
가상호스트 별로 File System을 설정한다. 또는 기본 가상호스트를 통해 모든 가상호스트에 일괄설정 할 수 있다.
# server.xml - <Server><VHostDefault><Options>
# vhosts.xml - <Vhosts><Vhost><Options>
<FileSystem Status="Active" DotDir="OFF">
<FileTime>origin</FileTime>
<FileStatus>200</FileStatus>
<DirStatus>301, 302, 400, 401, 403</DirStatus>
<Unlink>Purge</Unlink>
</FileSystem>
<FileTime> (기본: Origin)
파일시간을 제공할 때Origin
인 경우 원본에서 응답한 Last-Modified시간,Local
인 경우 로컬에 캐싱된 시간을 서비스한다. (Origin
인 경우) 원본서버에서 Last-Modified시간을 주지 않은 경우 다음과 같이 Unix 초기시간으로 제공된다.<FileSystem>
Status
속성이Inactive
라면 File System에서 접근할 수 없다. Active 로 설정해야 한다.<FileStatus> (기본: 200)
파일로 인식할 원본서버 HTTP 응답코드를 설정한다. 일반적으로는 200만을 설정하지만 특별한 제약은 없다.<DirStatus> (기본: 301, 302, 400, 401, 403)
디렉토리로 인식할 원본서버 HTTP 응답코드를 설정한다. 기본 값으로 302, 400, 401, 403등이 설정된다.
<Unlink> (기본: Purge)
파일삭제 요청이 들어온 경우 동작방식Purge
,Expire
,HardPurge
을 설정한다.
원본서버마다 HTTP 응답코드가 다양하게 해석될 수 있다. 그러므로 각각의 HTTP 응답코드 해석방식을 설정해야 한다.
대부분의 경우 원본서버에 존재하는 파일의 경우 200 OK 로 응답한다. 디렉토리 접근인 경우 403 Forbidden 응답이나 302 Found 로 다른 페이지로 Redirect시키기도 한다. 응답코드명을 comma(,)로 구분하여 설정하면 해당 HTTP 응답코드의 Body를 파일 또는 디렉토리로 인식한다. 설정되지 않은 응답코드에 대해서는 존재하지 않는 것으로 판단, File I/O가 실패한다.
파일속성¶
대부분 File I/O의 첫 번째 단계는 파일속성을 얻는 것이다. 파일을 open하기 전에 파일정보를 얻는 것은 당연한 순서다. Kernel이 파일속성을 서비스하는 과정을 STON관점에서 보면 다음과 같다. (/cachefs는 Mount경로이므로 Kernel이 생략한다.)

파일속성을 얻는 과정
Linux의 경우 파일과 디렉토리를 별도로 구분하지 않는다. 그러므로 특정 파일속성을 얻는 과정이 생각보다 복잡하다. 위 그림에서도 알 수 있듯이 디렉토리가 깊으면 깊을수록 중간 과정의(=필요 없는) 가상호스트 검색과 파일 접근이 발생하여 성능이 저하된다. 특히 /one 또는 /one/two처럼 웹 서비스라면 접근되지도 않을 경로의 요청이 발생하여 원본서버 부하를 발생시킨다. 물론 Caching되면 TTL(Time To Live) 시간 동안 접근은 발생하지 않지만 아름답지 않은 것만은 분명한다.
이런 구조적 부하를 휴리스틱(Heuristic)하게 해결하기 위해 DotDir
속성을 추가하였다.
DotDir
은 dot(.)이 요청된 경로에 없으면 디렉토리(Dir)로 인식하는 기능이다.
앞서 설명한 그림은 DotDir
이 OFF
인 상태이다.
DotDir
이 ON
인 경우는 다음과 같이 동작한다.

전역 DotDir
활성화( ON
)
Kernel에서 호출되는 과정이나 회수에는 변함이 없다. 하지만 요청된 경로에 dot(.)이 없으면 가상호스트까지 가지 않고 즉시 디렉토리로 응답하기 때문에 꼭 필요한 부분에서만 가상호스트와 파일이 참조된다. 이 기능은 대부분의 프로그래머들이 파일에만 확장자를 부여하고 디렉토리에는 그렇지 않다는 것에 착안한 기능이다. 그러므로 사용하기 전에 디렉토리 구조에 대해 반드시 확인이 필요하다.
<FileSystem>
은 DotDir
속성은 전역이다.
쉽게 말해 모든 가상호스트가 디렉토리에 dot(.)을 사용하지 않는다면 전역 DotDir
을 ON
으로 설정하시는 것이 아주 효과적이다.
물론 전역 DotDir
을 OFF
로 설정하고 가상호스트마다 별도로 설정할 수도 있다.
이 경우 다음 그림처럼 약간의 성능부하가 발생한다.

가상호스트 DotDir
활성화( ON
)
가상호스트 검색은 발생하지만 파일참조는 dot(.)이 있는 상태에서만 발생한다. 매우 빈번하게 호출되는 만큼 성능과 관련하여 반드시 이해할 것을 권장한다.
파일읽기¶
파일속성을 얻는 과정은 복잡하지만 정작 파일 읽기는 간단하다. 먼저 파일을 Open한다. 모든 파일은 당연히 ReadOnly이다. Write권한의 파일 접근은 실패한다. 최초 파일이 접근되는 경우 HTTP와 마찬가지로 원본서버에서 파일을 Caching한다. 파일을 요청한 프로세스가 기다리지 않도록 다운로드를 진행하면서 동시에 File I/O 서비스가 이루어진다.

파일 Open
이후 동작은 HTTP 서비스와 동일하다. 다만 HTTP의 경우 처음 결정된 Range에서 순차적(Sequential)인 파일접근이 발생하기 때문에 파일 전송에 유리한 면이 있다. 반면 File I/O의 경우 파일 크기와 상관없이 아주 작은 1KB단위의 read접근이 매우 많이 발생할 수 있다. 성능의 극대화를 위해 STON은 Cache모듈에 Readahead 를 구현했으며, 이를 통해 File I/O 성능을 극대화시켰다.
파일닫기(fclose등) 함수가 호출되거나 프로세스가 종료되는 경우 파일 handle은 Kernel에 의해 반납된다. 이는 HTTP 트랜잭션이 종료되는 것과 같다.
파일삭제¶
Caching된 파일은 STON에 의해 관리되지만 프로세스가 삭제요청을 보낼 수 있다. STON은 다양한 Purge 방법을 제공하고 있으므로 이런 요청에 쉽게 대응할 수 있다.
예를 들어 <Unlink>
가 expire
로 설정되어 있는 경우 파일삭제 요청에 대해 해당 파일을 expire하도록 동작한다.
Kernel에서 다시 해당 파일에 접근한다면 expire된 상태이므로 원본서버에서 변경여부를 확인한 뒤 변경되지 않았다면 해당 파일을 다시 서비스한다.
파일확장¶
HTTP의 경우 다음과 같이 URL을 이용하여 원본 파일을 동적으로 가공할 수 있다.
# HTTP를 통해 /video.mp4의 0~60초 구간을 Trimming한다.
http://www.example.com/video.mp4?start=0&end=60
이와 같은 QueryString방식은 HTTP와 File System 모두 호출규격을 동일하게 사용할 수 있다.
# "/video.mp4의 0~60초 구간을 Trimming한" 로컬파일에 접근한다.
/cachefs/www.example.com/video.mp4?start=0&end=60
하지만 MP4HLS나 DIMS처럼 원본 URL뒤에 가공옵션을 디렉토리 형식으로 명시하는 방식은 File I/O에 문제가 있다.
/cachefs/image.winesoft.com/img.jpg/12AB/resize/500x500/
/cachefs/www.winesoft.com/video.mp4/mp4hls/index.m3u8
“파일속성 얻기” 에서 설명한 바와 같이 LINUX는 경로 각 부분의 속성을 매번 물어본다. STON관점에서는 현재 물어보는 경로 뒤에 추가 경로가 있는지 알 수 없기 때문에 가공되지 않은 파일을 서비스하게 된다.
이 문제를 극복하기 위해서 STON은 별도의 구분자로 <FileSystem>
의 Separator (기본: ^)
속성을 사용한다.
/cachefs/image.winesoft.com/img.jpg^12AB^resize^500x500^
/cachefs/www.winesoft.com/video.mp4^mp4hls^index.m3u8

MP4HLS 접근
STON 내부에서는 Separator
를 slash(/)로 변경하여 HTTP와 동일한 호출규격을 사용한다.
이를 적극적으로 활용할 경우 다음과 같이 불필요 File I/O접근을 완전히 제거할 수 있다.

극도로 최적화된 접근
Wowza 연동¶
File System을 이용해 손쉽게 Wowza를 연동할 수 있다. STON이 Mount된 경로를 Wowza의 파일경로로 설정하는 것으로 모든 설정이 완료된다.
1. [STON - 전역설정] 파일시스템 설정 ON
전역설정(server.xml)에 다음과 같이
<FileSystem>
을ON
으로 설정한다. (예제에서는 Mount경로를 “/cachefs”로 설정한다.)# server.xml - <Server><Cache> <FileSystem Mount="/cachefs" DotDir="OFF" Separator="^">ON</FileSystem>또는 WM의 전역설정 - 파일시스템에서 다음과 같이 파일 시스템을 “사용한다”로 설정한다.
![]()
설정 후 반드시 STON을 재시작해야 Mount된다.
2. [STON - 가상호스트] 파일시스템 접근허가 & 응답코드 설정
가상호스트의 파일시스템 접근을 Active시킨다. 원본서버 응답코드에 따른 파일/디렉토리 판단정책도 설정한다. 여기서는 가상호스트 기본 설정(server.xml)을 예로 설명하지만 각각의 가상호스트(vhosts.xml)에서 개별적으로 설정할 수 있다.
# server.xml - <Server><VHostDefault><Options> # vhosts.xml - <Vhosts><Vhost><Options> <FileSystem Status="Active" DotDir="OFF"> <FileStatus>200</FileStatus> <DirStatus>301, 302, 400, 401, 403</DirStatus> </FileSystem>또는 WM의 가상호스트 - 파일시스템에서 다음과 같이 접근을 “허가한다”로 설정한다.
![]()
응답코드를 설정한다.
3. [Wowza] Storage 경로 설정
Wowza설치경로 /Conf/Application.xml 파일을 다음과 같이 STON이 Mount된 경로를 바라보도록 편집한다.
<Streams> <StreamType>default</StreamType> <StorageDir>/cachefs/example.com</StorageDir> <KeyDir>${com.wowza.wms.context.VHostConfigHome}/keys</KeyDir> </Streams>
4. [Wowza] VOD 경로설정
Wowza설치경로 /Conf/vod/Application.xml 파일을 다음과 같이 STON이 Mount된 경로를 바라보도록 편집한다.
<Streams> <StreamType>default</StreamType> <StorageDir>/cachefs/example.com</StorageDir> <KeyDir>${com.wowza.wms.context.VHostConfigHome}/keys</KeyDir> </Streams>
5. 플레이어 테스트
Wowza 테스트 플레이어로 로컬에 존재하지 않는(=STON이 캐싱해야 하는) 영상을 RTMP로 재생한다.
![]()
테스트엔 적절한 영상이 필요합니다.
19장. 최적화와 그 밖의 것들¶
이 장에서는 최적화와 그 밖의 잡다하지만 깊이 있는 주제에 대해 다룬다. 최적화는 고성능(High Performance)을 위한 방법이며 이는 우리가 추구하는 가장 큰 가치다. 엔터프라이즈 환경에서의 고성능은 주어진 하드웨어 자원을 최대한 활용하는 것을 의미하기도 한다.
그 중 메모리는 모든 설계 및 정책을 결정하는 가장 중요한 자원이다. 특히 인덱싱(요청된 URL을 빠르게 찾는 것)에 대해서는 반드시 이해해야 한다. 왜냐하면 서비스 품질을 결정짓는 것은 인덱싱이기 때문이다. 앞으로 설명할 모든 내용은 다음 표 “물리 메모리 크기에 따른 기본설정”와 관련이 있다.
Physical RAM | System Free | Contents | Caching Count | Sockets |
---|---|---|---|---|
1GB | 409.60MB | 188.37MB | 219,469 | 5,000 |
2GB | 819.20MB | 446.74MB | 520,494 | 10,000 |
4GB | 1.60GB | 963.49MB | 1,122,544 | 20,000 |
8GB | 3.20GB | 2.05GB | 2,440,422 | 20,000 |
16GB | 6.40GB | 4.45GB | 5,303,733 | 20,000 |
32GB | 12.80GB | 9.25GB | 11,030,356 | 20,000 |
64GB | 25.60GB | 18.85GB | 22,483,603 | 20,000 |
128GB | 51.20GB | 38.05GB | 45,390,095 | 20,000 |
인덱싱¶
인덱싱 모드를 설명하기에 앞서 Hot콘텐츠와 Cold콘텐츠의 개념을 이해해야 한다.

원본으로부터 캐싱한 콘텐츠는 로컬 디스크에 저장된다. 해당 콘텐츠가 접근될 때마다 매번 디스크에서 읽어 전송하면 당연히 성능이 저하된다. 따라서 자주 접근되는 콘텐츠를 메모리에 적재해 놓으면 고성능을 얻을 수 있다. 이렇게 메모리에 적재된 콘텐츠를 Hot, 디스크에만 위치한 콘텐츠를 Cold라고 부른다.
인덱싱은 Hot과 Cold콘텐츠를 찾는 방식을 의미하며 이는 성능과 직결된다. 기본은 메모리 인덱싱이다.
# server.xml - <Server><Cache>
<Indexing>Memory</Indexing>
메모리 인덱싱에서는 Cold가 존재하지 않는다. 모든 파일에 대한 정보는 메모리에 적재되기 때문에 메모리에서 찾을 수 없다면 원본서버에서 신규로 다운로드 한다. 검색시간이 매우 짧기 때문에 그 만큼 고성능과 빠른 서비스 품질을 얻을 수 있다. 하지만 메모리 저장공간의 한계로 인해 캐싱 개수에 한계가 있다. 그 한계는 앞선 표의 Caching Count를 참고한다.
디스크 인덱싱은 Hot에 없는 경우 원본으로 가기 전에 Cold에서 콘텐츠를 찾는다.
# server.xml - <Server><Cache>
<Indexing>Disk</Indexing>
이 방식은 메모리 제한을 받지 않기 때문에 Caching Count에 제한이 없다. Hot 콘텐츠의 경우 빠른 품질을 보장하지만, Cold의 경우 디스크를 사용하기 때문에 상대적으로 느리다. 간단히 정리하면 Hot은 메모리 속도, Cold는 디스크 속도에 수렴한다.
디스크 인덱싱을 사용할 경우 SSD를 사용할 것을 강력히 권장한다. 인덱싱은 STON이 설치된 디스크에서만 수행된다. STON은 일반적으로 OS와 같은 디스크에 설치되기 때문에 OS디스크만 SSD로 사용해도 고성능을 기대할 수 있다.
주석
SSD의 수명은 접근 빈도보다 Write되는 양에 의해 결정된다. Intel이나 Samsung등에서 공급하는 SSD의 경우 최소 600TB의 Write수명을 보장한다. 이를 단순히 계산해보면 하루에 20GB씩 Write할 경우 10년 정도의 수명을 예측할 수 있다. STON에서의 Write의 99%는 Log다. 이런 관점에서 Log를 SSD가 아닌 다른 디스크(SAS나 SATA등)에 기록하도록 하면 내구성을 보장할 수 있다.
경고
인덱싱은 동적으로 변경할 수 없을 뿐만 아니라 변경하여도 안정성이 보장되지 않는다. 그러므로 모드를 변경한 뒤 Caching 초기화 를 진행해야 안전하게 서비스할 수 있다.
메모리 구조¶
캐시서버와 범용 웹서버의 동작방식은 유사하나 목적은 매우 다르다. STON의 구조와 동작방식을 상세히 이해하면 보다 최적화된 서비스가 가능하다. 최적화의 목적은 아래와 같다.
높은 처리량. 성능저하 없이 수 만개의 세션을 동시에 처리할 수 있다.
빠른 반응성. 클라이언트에게 지연없는 서비스를 제공한다.
원본서버 부하절감. 원본서버 부하는 자칫 전체장애로 이어진다.
다음 그림은 STON을 8GB와 16GB메모리 장비에서 구동시켰을 때의 메모리 구성이다.

메모리는 STON이 사용하는 메모리와 사용하지 않는 메모리(Free)로 나눈다. STON이 사용하는 메모리는 파일, 소켓같이 서비스 규모에 따라 달라지는 자원 개수와 관련이 있다.
주석
시스템 부하의 근본은 디스크 I/O 때문이다. 당신은 “얼마나 많은 Contents를 Caching해야 디스크 I/O를 줄일 수 있는가?” 에 대해 고민해야 한다.
메모리 조절¶
메모리 구조 는 구동될 때 물리 메모리 크기에 기반하여 계산된다.
# server.xml - <Server><Cache>
<SystemMemoryRatio>100</SystemMemoryRatio>
<SystemMemoryRatio> (기본: 100)
물리메모리를 기준으로 사용할 메모리 비율을 설정한다.
예를 들어 8GB장비에서 <SystemMemoryRatio>
를 50으로 설정하면 물리 메모리가 4GB인 것처럼 동작한다.
이는 메모리를 점유하는 다른 프로세스와 같이 구동될 때 유용하게 사용될 수 있다.
좀 더 구체적으로 서비스 형식에 따라 메모리에 적재되는 데이터 비율을 조절하면 효과적이다.
# server.xml - <Server><Cache>
<ContentMemoryRatio>50</ContentMemoryRatio>
<ContentMemoryRatio> (기본: 50)
STON이 사용하는 전체 메모리 중 서비스 데이터 메모리 적재비율을 설정한다.
예를 들어 게임 포탈처럼 파일개수는 적지만 컨텐츠 크기가 클 경우엔 이 수치를 늘리면 파일 I/O가 감소된다. 반대로 아주 작은 파일이 많은 경우는 반대로 줄이는 설정이 유용할 수 있다.
시스템 Free 메모리¶
OS(Operating System)가 느리면 어떠한 프로그램도 제 성능을 내지 못한다. STON은 OS를 위해 일부 메모리를 사용하지 않는다. OS의 성능을 극대화하기 위해서며 이를 시스템 Free메모리라 부른다.
주석
이에 대해 권위있는 설명을 제시하고 싶으나 아쉽게도 찾지 못하였다. 구글링을 통해 가장 많이 인용된 글 을 제시한다.
Physical RAM | System Free |
---|---|
1GB | 409.6MB |
2GB | 819.2MB |
4GB | 1.6GB |
8GB | 3.2GB |
16GB | 6.4GB |
32GB | 12.8GB |
64GB | 25.6GB |
128GB | 51.2GB |
고급 사용자의 경우 서비스 형태에 맞추어 Free메모리 비율을 줄일 수 있다. Free메모리가 줄어들면 더 많은 Contents를 메모리에 적재할 수 있다.
# server.xml - <Server><Cache>
<SystemFreeMemoryRatio>40</SystemFreeMemoryRatio>
<SystemFreeMemoryRatio> (기본: 40, 최대: 40)
물리 메모리를 기준으로 설정된 비율만큼을 Free메모리로 남겨둔다.
Caching 서비스 메모리¶
클라이언트에게 전송할 컨텐츠를 Caching하는 메모리이다. 한번 디스크에서 메모리로 적재된 컨텐츠는 메모리 부족현상이 발생하지 않는다면 계속 메모리에 존재한다. 문제는 메모리 부족현상은 항상 발생한다는 점이다.

위 그림처럼 전송해야할 컨텐츠는 디스크에 가득한데 실제 메모리에 적재할 수 있는 용량은 아주 제한적이다. 32GB의 물리 메모리를 장착한다해도 고화질 동영상이나 게임 클라이언트의 크기를 감안한다면 그리 넉넉한 편은 아니다. 아무리 효율적으로 메모리를 관리해도 물리적인 디스크 I/O속도에 수렴할 수 밖에 없다.
가장 효과적인 방법은 Contents메모리 공간을 최대한 확보하여 디스크 I/O를 줄이는 것이다. 다음은 물리 메모리 기준으로 STON이 기본으로 설정하는 최대 Contents메모리 크기이다.
Physical RAM | Contents | Caching Count |
---|---|---|
1GB | 188.37MB | 219,469 |
2GB | 446.74MB | 520,494 |
4GB | 963.49MB | 1,122,544 |
8GB | 2.05GB | 2,440,422 |
16GB | 4.45GB | 5,303,733 |
32GB | 9.25GB | 11,030,356 |
64GB | 18.85GB | 22,483,603 |
128GB | 38.05GB | 45,390,095 |
Socket 메모리¶
소켓도 메모리를 사용한다. 4GB이상의 장비에서 STON은 2만개의 소켓을 기본으로 생성한다. 소켓 1개=10KB, 1만개당 97.6MB의 메모리를 사용하므로 약 195MB의 메모리가 기본으로 소켓에 할당된다.
Physical RAM | Socket Count | Socket Memory |
---|---|---|
1GB | 5천 | 97.6MB |
2GB | 1만 | 195MB |
4GB 이상 | 2만 | 390MB |
다음 그림처럼 소켓을 모두 사용하면 자동으로 소켓이 늘어난다.

위 그림과 같이 증설되어 3만개의 소켓을 사용한다면 총 240MB의 메모리가 소켓에 할당된다. 필요한 소켓을 필요한만큼만 사용하는 것은 아무 문제가 없어 보인다. 하지만 사용하지 않는 소켓을 지나치게 많이 설정해놓는 것은 메모리 낭비다. 예를 들어 10Gbps장비에서 사용자마다 10Mbps의 전송속도를 보장한다고 가정했을 때 다음 공식에 의하여 최대 동시 사용자는 1,000명이다.
10,000Mbps / 10Mbps = 1,000 Sessions
이 경우 STON이 최초 생성하는 2만개 중 19,000개에 해당하는 약 148MB는 낭비가 되는 셈이다. 이 148MB를 Contents에 투자한다면 효율을 더 높일 수 있다. 최소 소켓수를 설정하면 메모리를 보다 효율적으로 사용할 수 있다.
최소 소켓수. 최초에 할당되는 소켓수를 의미한다.
증설 소켓수. 소켓이 모두 사용 중(Established)일 때 설정한 개수만큼 소켓을 증설한다.
또 하나의 중요한 변수는 클라이언트 Keep-Alive시간 설정이다. (세션관리 참조)

연결된 모든 소켓이 데이터 전송 중에 있는 것은 아니다. IE, Chrome과 같은 브라우저들은 다음에 발생할 HTTP전송을 위해 소켓을 서버에 접속해 놓은 상태로 유지한다. 실제로 쇼핑몰의 경우 연결되어 있는 세션 중 아무런 데이터 전송이 발생하지 않고 그저 붙어 있는 세션의 비율은 적게는 50%에서 많게는 80%에 이른다.

Keep-Alive시간을 길게 줄수록 소켓의 재사용성은 좋아지지만 유지되는 Idle소켓의 개수가 증가하므로 메모리 낭비가 심해진다. 그러므로 서비스에 맞는 적절한 클라이언트 Keep-Alive시간을 설정하는 것이 중요하다.
TCP Segmentation Offload¶
중요
10G NIC를 사용한다면 TSO(TCP Segmentation Offload)를 OFF로 설정하길 권장한다.
TCP는 전송시 패킷을 분할(Segmentation)하는데, 이 작업을 CPU가 아닌 NIC가 수행하도록 설정하는 것이 TSO이다. (기본 값은 ON이다.) 하지만 10G NIC 서비스 환경에서 우리는 이와 관련된 많은 장애를 겪었다.
- TCP 패킷 유실 및 지연
- TCP 연결 종료
- Load Average의 비정상적인 증가
결론적으로 TSO는 모두의 기대만큼 높은 성능을 내지 못하는 것으로 추정된다. (NIC만 1G로 바꿔도 이런 문제는 발생하지 않았다.) 결론적으로 TSO를 OFF로 설정함으로써 서비스는 정상화되었다. 이에 따른 CPU 사용량은 우려할 수준이 아니며 서비스 규모와 비례하는 정직한 지표를 보여 준다.
TSO 설정은 다음과 같이 설정/확인할 수 있다. (K의 대/소문자에 유의한다.)
# ethtool -K ethX tso off // TSO OFF 설정
# ethtool -k ethX // 설정 열람
...
tcp segmentation offload: on
...
클라이언트 접속 제한¶
제한없이 클라이언트 요청을 모두 허용하면 시스템에 지나친 부하가 발생할 수 있다. 시스템 과부하는 사실상 장애이다. 적절한 수치에서 클라이언트 요청을 거부하여 시스템을 보호한다.
# server.xml - <Server><Cache>
<MaxSockets Reopen="75">80000</MaxSockets>
<MaxSockets> (기본: 80000, 최대: 100000)
연결을 허용할 최대 클라이언트 소켓 수. 이 수치를 넘으면 신규 클라이언트 접속을 즉시 닫는다.<MaxSockets>
의Reopen (기본: 75%)
비율만큼 소켓 수가 감소하면 다시 접속을 허용한다.

(기본 설정에서) 전체 클라이언트 소켓 수가 8만을 넘으면 신규 클라이언트 접속은 즉시 종료된다. 전체 클라이언트 소켓 수가 6만(8만의 75%)이 되면 다시 접근을 허용한다.
예를 들어 3만개의 클라이언트 세션을 처리할 때 원본 서버들이 모두 한계에 도달하면 이 수치를 3~4만 정도로 설정하는 것이 좋다. 이로 인해 얻을 수 있는 효과는 다음과 같다.
- 별다른 Network 구성(e.g. L4 세션조절 등)이 필요 없다.
- 불필요한(원본 부하로 처리될 수 없는) 클라이언트 요청을 방지한다.
- 서비스의 신뢰성을 높인다. 서비스 Burst 이후 재시작 등 점검 작업이 필요 없다.
HTTP 클라이언트 세션 수¶
HTTP 클라이언트 연결을 처리하기 위한 초기/증설 세션 수를 설정한다.
# server.xml - <Server><Cache>
<HttpClientSession>
<Init>20000</Init>
<TopUp>6000</TopUp>
</HttpClientSession>
<Init>
STON 시작시 미리 생성해놓는 소켓 수<TopUp>
생성해놓은 소켓 수를 초과했을 때 추가로 생성할 소켓 수
별도로 설정하지 않을 경우 물리 메모리 크기에 따라 자동으로 설정된다.
물리메모리 | <Init>, <TopUp> |
---|---|
1GB | 5천, 1천 |
2GB | 1만, 2천 |
4GB | 2만, 4천 |
8GB 이상 | 2만, 6천 |
제한적인 환경에서 적은 수의 소켓만으로도 서비스가 가능할 때 소켓 수를 줄이면 메모리를 절약할 수 있다.
Request hit ratio¶
먼저 클라이언트의 HTTP요청이 어떻게 처리되는지 이해해야 한다. 캐시처리 결과는 Squid와 동일하게 TCP_*로 명명되며 각 표현마다 캐시서버가 처리한 방식을 의미한다.
TCP_HIT
요청된 리소스(만료되지 않음)가 캐싱되어 있어 즉시 응답함.TCP_IMS_HIT
IMS(If-Modified-Since)헤더와 함께 요청된 리소스가 만료되지 않은 상태로 캐싱되어 있어 304 NOT MODIFIED로 응답함. TTLExtensionBy4xx, TTLExtensionBy5xx설정에 해당하는 경우에도 이에 해당함.TCP_REFRESH_HIT
요청된 리소스가 만료되어 원본서버 확인(원본 미변경, 304 NOT MODIFIED) 후 응답함. 리소스 만료시간 연장됨.TCP_REF_FAIL_HIT
TCP_REFRESH_HIT과정 중 원본서버에서 확인이 실패(접속실패, 전송지연)한 경우 만료된 컨텐츠로 응답함.TCP_NEGATIVE_HIT
요청된 리소스가 비정상적인 상태(원본서버 접속/전송 실패, 4xx응답, 5xx응답)로 캐싱되어 있고 해당상태를 응답함.TCP_REDIRECT_HIT
서비스 허용/거부/Redirect 조건에 의해 Redirect를 응답함.TCP_MISS
요청된 리소스가 캐싱되어 있지 않음(=최초 요청). 원본서버에서 가져온 결과를 응답함.TCP_REF_MISS
요청된 리소스가 만료되어 원본서버 확인(원본 변경, 200 OK) 후 응답함. 새로운 리소스가 캐싱됨.TCP_CLIENT_REFRESH_MISS
요청을 원본서버로 바이패스.TCP_ERROR
요청된 리소스가 캐싱되어 있지 않음(=최초 요청). 원본서버 장애(접속실패, 전송지연, 원본배제)로 인해 리소스를 캐싱하지 못함. 클라이언트에게 500 Internal Error로 응답함.TCP_DENIED
요청이 거부되었음.
이상을 종합하여 Request hit ratio계산 공식은 다음과 같다.
TCP_HIT + TCP_IMS_HIT + TCP_REFRESH_HIT + TCP_REF_FAIL_HIT + TCP_NEGATIVE_HIT + TCP_REDIRECT_HIT
------------------------------------------------------------------------------------------------
SUM(TCP_*)
Byte hit ratio¶
클라이언트에게 전송한 트래픽(Client Outbound)대비 원본서버로부터 전송받은 트래픽(Origin Inbound)의 비율을 나타낸다. 원본서버 트래픽이 클라이언트 트래픽보다 높은 경우 음수가 나올 수 있다.
Client Outbound - Origin Inbound
--------------------------------
Client Outbound
원본서버 장애상황 정책¶
고객이 언제든지 원본서버를 점검 할 수 있도록 하는 것이 개발팀의 목표다. 원본서버의 장애가 감지되면 해당 서버는 자동으로 배제되어 복구모드로 전환된다. 장애서버가 재가동되었더라도 정상 서비스 상태를 확인해야만 다시 투입한다.
만약 모든 원본서버의 장애를 감지한 경우 현재 캐싱된 컨텐츠로 서비스를 진행한다. TTL이 만료된 컨텐츠는 원본서버가 복구될 때까지 자동으로 연장된다. 심지어 Purge된 컨텐츠의 경우에도 원본서버에서 캐싱할 수 없다면 복구시켜 서비스에 문제가 없도록 동작한다. 최대한 클라이언트에게 장애상황을 노출해선 안된다는 정책이다. 완전 장애상황에서 신규 컨텐츠 요청이 들어오면 다음과 같은 에러 페이지와 이유가 명시된다.

왠만하면 이런 화면은 보여주기 싫다.
시간단위 표현과 범위¶
기준 시간이 “초”인 항목에 대하여 문자열로 시간표현이 가능하다. 다음은 지원되는 시간표현 목록과 환산된 초(sec) 다.
표현 | 환산 |
---|---|
year(s) | 31536000 초 (=365 days) |
month(s) | 2592000 초 (=30 days) |
week(s) | 604800 초 (=7 days) |
day(s) | 86400 초 (=24 hours) |
hour(s) | 3600 초 (=60 mins) |
minute(s), min(s) | 60 초 |
second(s), sec(s), (생략) | 1 초 |
다음과 같이 조합된 시간표현이 가능하다.
1year 3months 2weeks 4days 7hours 10mins 36secs
현재 지원대상은 다음과 같다.
- Custom TTL의 시간표현
- TTL의 Ratio를 제외한 모두
- ClientKeepAliveSec
- ConnectTimeout
- ReceiveTimeout
- BypassConnectTimeout
- BypassReceiveTimeout
- ReuseTimeout
- Recovery의 Cycle속성
- Bandwidth Throttling
Emergency 모드¶
내부적으로 모든 가상호스트가 MemoryBlock을 공유하면서 데이터를 관리하도록 설계되어 있다. 신규 메모리가 필요한 경우 참조되지 않는 오래된 MemoryBlock을 재사용하여 신규 메모리를 확보한다. 이 과정을 Memory-Swap이라고 부른다. 이런 구조를 통해 장기간 운영하여도 안정성을 확보할 수 있다.

콘텐츠 데이터는 MemoryBlock에 담겨 서비스된다.
위 그림의 우측 상황처럼 모든 MemoryBlock이 사용 중이어서 재사용할 수 있는 MemoryBlock이 존재하지 않는 상황이 발생할 수 있다. 이때는 Memory-Swap이 불가능해진다. 예를 들어 모든 클라이언트가 서로 다른 데이터 영역을 아주 조금씩 다운로드 받거나 원본서버에서 서로 다른 데이터를 아주 조금씩 전송하는 상황이 동시에 발생하는 경우가 최악이다. 이런 경우 시스템으로부터 새로운 메모리를 할당받아 사용하는 것도 방법이다. 하지만 이런 상황이 지속될 경우 메모리 사용량이 높아진다. 메모리 사용량이 과도하게 높아질 경우 시스템 메모리스왑을 발생시키거나 최악의 경우 OS가 STON을 종료시키는 상황이 발생할 수 있다.
주석
Emergency 모드란 메모리 부족상황이 발생할 경우 임시적으로 신규 MemoryBlock의 할당을 금지시키는 상황을 의미한다.
이는 과다 메모리 사용으로부터 스스로를 보호하기 위한 방법이며, 재사용가능한 MemoryBlock이 충분히 확보되면 자동 해지된다.
# server.xml - <Server><Cache>
<EmergencyMode>OFF</EmergencyMode>
<EmergencyMode>
OFF (기본)
사용하지 않는다.ON
사용한다.
Emergency모드일 때 STON은 다음과 같이 동작합니다.
이미 로딩되어 있는 컨텐츠는 정상적으로 서비스된다.
바이패스는 정상적으로 이루어진다.
로딩되어 있지 않은 컨텐츠에 대해서는 503 service temporarily unavailable로 응답한다. TCP_ERROR상태가 증가한다.
Idle 클라이언트 소켓을 빠르게 정리한다.
신규 컨텐츠를 캐싱할 수 없다.
TTL이 만료된 컨텐츠를 갱신하지 않는다.
SNMP의 cache.vhost.status와 XML/JSON통계의 Host.State 값이 “Emergency”로 제공된다.
Info로그에 Emergency모드로 전환/해제를 다음과 같이 기록한다.
2013-08-07 21:10:42 [WARNING] Emergency mode activated. (Memory overused: +100.23MB) ...(생략)... 2013-08-07 21:10:43 [NOTICE] Emergency mode inactivated.
디스크 Hot-Swap¶
서비스 중단없이 디스크를 교체한다.
파라미터는 반드시 <Disk>
설정과 같아야 한다.
http://127.0.0.1:10040/command/unmount?disk=...
http://127.0.0.1:10040/command/umount?disk=...
배제된 디스크는 즉시 사용되지 않으며 해당 디스크에 저장되었던 모든 컨텐츠는 무효화된다. 관리자에 의해 배제된 디스크의 상태는 “Unmounted”로 설정된다.
디스크를 서비스에 재투입하려면 다음과 같이 호출한다.
http://127.0.0.1:10040/command/mount?disk=...
재투입된 디스크의 모든 콘텐츠는 무효화된다.
5부. 부록¶
Appendix A: Graph¶
모든 MRTG통계는 PNG포맷 그래프로 제공된다. 호출 규칙은 자원 뒤에 단위가 붙는 형식이다.
# 5가지의 CPU 그래프 (dash, day, week, month, year)
http://127.0.0.1:10040/graph/cpu_dash.png
http://127.0.0.1:10040/graph/cpu_day.png
http://127.0.0.1:10040/graph/cpu_week.png
http://127.0.0.1:10040/graph/cpu_month.png
http://127.0.0.1:10040/graph/cpu_year.png
모든 그래프는 5가지 타입으로 제공된다.
한 그래프에는 최소 1개에서 최대 3개의 선이 그려진다. Main 라인은 녹색, Sub 라인은 파란색으로 그려진다. 또한 “Week” 그래프 이상부터는 Peak 라인이 제공된다. Peak 라인은 이전 단위에서 가장 큰 수치를 핑크색으로 그린다.
전역자원¶
전역자원 그래프는 시스템 상태 또는 STON과 관련된 자원들에 대해 서비스한다. 아래 표에서 *는 타입(dash, day, week, month, year) 중 한 가지를 의미한다.
가상호스트¶
가상호스트 그래프는 전체 또는 개별 가상호스트의 상태에 대해 서비스한다. vhost파라미터를 이용하여 특정 가상호스트를 지정할 수 있으며, 생략된 경우 전체 가상호스트의 합을 제공한다.
http://127.0.0.1:10040/graph/vhost/mem_day.png?vhost=example.com
아래 표에서 *는 타입(dash, day, week, month, year) 중 한 가지를 의미한다.
클라이언트 트랜잭션 완료¶
/graph/vhost/client_http_res_complete_*.png
Main
완료된 클라이언트 HTTP응답회수Sub
클라이언트 HTTP 요청회수
Appendix B: Cacti 모니터링¶
이 장에서는 Cacti 의 Graph Tree를 사용하여 다수의 STON을 통합 모니터링 하는 방법에 대해 설명한다. 다음 2가지 사항이 전제된다.
- Cacti가 설치된 서버
- SNMP 활성화 ( 11장. SNMP 참고)
Template 추가¶
STON에서 제공하는 Host Template을 사용하면 모니터링 환경을 쉽게 구축할 수 있다. ( 다운로드 )

Import Templates 메뉴를 선택한다.

cacti_host_template_ston.xml을 Import한다.
Device 등록¶
STON을 Cacti의 Device로 등록한다.

[Devices] 메뉴를 선택한다.

[Devices] 메뉴의 [Add] 버튼을 클릭한다.

Devices 항목을 작성한다.
- ① 대상 STON의 이름을 작성한다.
- ② 대상 STON의 IP를 입력한다.
- ③ ”STON”을 선택한다.
- ④ “Public”을 선택한다.
- ⑤ 기본 포트 161을 입력한다.
Create 버튼을 클릭하여 Device를 연동한다.

정상적으로 연동되었다.

연동에 실패하였다.
주석
SNMP 연동 실패시
- STON의 SNMP가 활성화되었는지 확인한다.
- SNMP Port 번호가 STON의 SNMP Port번호와 일치 한지 확인한다.
Device 연동에 성공하면 STON Template 에서 제공하는 18가지 항목의 그래프를 사용 할 수 있다.

“Create Graphs for this Host” 링크를 클릭한다.

18가지 그래프가 제공된다.
[Create] 버튼을 클릭하여 생성된 그래프를 확인한다.

그래프가 생성되었다.
Graph Tree 생성¶
Graph Tree를 생성한다.

[Graph Trees] 클릭한다.

우측 상단의 [Add]를 클릭한다.

Graph Tree 생성한다.
STON을 Graph Tree에 추가한다.

[Tree Items] 메뉴에서 [Add]를 클릭한다.

[Tree Items]항목을 작성 한다.
- ① “Host”를 선택한다.
- ② 추가할 “Devices”로 선택한다.
- ③ “Graph Template”로 선택 한다.
Appendix C: 동적페이지 주의사항¶
동적 페이지란 웹 프로그래밍 언어(JSP, PHP 등)로 개발된 웹 페이지를 의미하며, 주로 클라이언트 요청에 따라 내용이 변경되는 특징을 가진다. 다음과 같은 동적 페이지를 적당 시간동안 캐싱하면 웹서버/WAS/데이터베이스의 부하를 획기적으로 감소시킬 수 있다.
- 실시간 순위 (실시간 검색어 또는 랭킹)
- 검색 결과
- 조회 용 API
- 상품 상세 페이지 (재고)
캐싱해서는 안되는 페이지는 다음과 같다.
개인계정
캐싱한다는 의미는 내가 열람한 페이지가 다른 사람에게도 공유된다는 의미이다. 누구도 내 개인 정보가 다른 사람에게 노출되는 것을 원하지 않는다. 기술적으로 대부분의 웹 사이트에서 개인정보는 로그인 후에 사용이 가능하다. 웹 서버에서 로그인 여부를 확인하는 조건을 STON에 ‘바이패스’하도록 설정해야 한다.
결제
비로그인 상태에서 결제가 가능한 서비스도 있다. 결제 단계의 모든 페이지는 캐싱 예외 조건으로 설정해야 한다.
Cookie 생성
Cooike는 클라이언트 고유의 정보를 담고 있는 경우가 많다. A사용자를 위해 생성된 Cookie가 B사용자에게 전달되면 큰 사고로 이어진다. 이 때문에 STON은 원본서버가 제공하는 Cookie헤더를 무시하도록 개발되었다.
‘쓰기(Write)’ API
읽기 API는 1초만 캐싱해도 효과가 있지만 ‘쓰기’ API를 캐싱할 경우 유효하지 않은 결과 값이 리턴되어 오동작할 수 있다.
번호표 발급
콘서트 티켓처럼 선착순으로 예매가 진행되는 경우를 의미한다. 보통 WAS나 전용 장비를 써서 진행되는 경우가 많다.
Appendix D: 릴리스 노트¶
v2.4.x¶
2.4.2 (2017.1.18)¶
- 가상호스트 링크 추가
버그수정
- 원본 서버가 Content-Length헤더에 음수 값을 줄 경우 비정상 종료 되는 증상
- MP3 HLS - 원본 서버와의 통신이 불안정 할 경우 간헐적으로 비정상 종료 되는 증상
2.4.1 (2016.11.24)¶
기능개선/정책변경
- 원본 HTTP 응답에서 reason phrases가 없는 경우에도 처리 할 수 있도록 정책 변경
- DIMS – 이미지 확대 시 캔버스만 키우는 기능 추가
버그수정
- 압축 기능 사용 시 아주 낮은 확률로 압축 된 파일이 깨지는 증상 수정
- VLC 플레이어에서 M4A HLS가 재생되지 않는 문제 수정
- DIMS를 이용해서 이미지 변환시 변환 크기를 입력하지 않을 경우 비정상 종료되는 증상
v2.3.x¶
2.3.7 (2016.09.26)¶
기능개선/정책변경
- dims 기능을 이용해서 이미지 변환시 시스템 자원 사용량을 제한하도록 정책 변경
- Health-Checker 기능 사용시 Standby 원본 서버도 검사하도록 정책 변경
버그수정
- handling-http-requests-compression 기능의 ON/OFF 설정이 반영되지 않던 버그 수정
2.3.6 (2016.08.16)¶
기능개선/정책변경
- 일부 투명 PNG를 JPG로 포멧 변환시 배경이 검은색으로 변경되는 문제 수정
- 비정상적인 클라이언트 소켓 처리 정책 강화
버그수정
- DIMS변환 중 Hardpurge API를 호출 할 경우 간헐적으로 비정상 종료 되던 증상
2.3.5 (2016.07.01)¶
기능개선/정책변경
- Native HLS 모듈을 사용하는 플레이어와의 호환성 강화
- DIMS의 Crop 기능은 비율을 유지 하지 않고 입력한 크기로 Crop 하도록 정책 변경
버그수정
- Health-Checker 기능이 활성화 되어 있는 상태에서 원본상태 초기화 API 호출시 간헐적으로 비정상 종료되는 문제 수정
2.3.4 (2016.06.03)¶
기능개선/정책변경
- 32bit atom으로 인코딩된 4기가 이상의 MP4 파일 지원
- unknown access 로그에 Host 헤더 값 추가
- WM - 보안권고 사항으로 STON 최초 설치 시 Apache manual 폴더 삭제
- WM - STON 최초 설치 시 Apache 구동 계정인 winesoft 계정을 nologin 권한으로 생성하도록 변경
버그수정
- HLS - 일부 영상에서 CPU를 과점유 하던 증상
- HTTP 요청이 바이패스 될 때 낮은 확률로 비정상 종료 되던 증상
- Access 로그에 클라이언트 IP가 0.0.0.0 으로 기록 되던 증상
- 가상호스트가 260개 이상일 경우 설정 파일이 백업되지 않던 증상
2.3.3 (2016.04.26)¶
버그수정
- [2.3.0 ~ 2.3.2] 원본서버 Host 설정과 Dims, 압축 설정이 함께 되어 있는 경우 404 에러 코드를 응답하는 증상
- SNMP View 생성 후 삭제시 CPU 과점유 증상
- WM - SNMP GlobalMin 값을 0으로 설정 할 수 없던 증상
2.3.2 (2016.03.22)¶
기능개선/정책변경
- mp3-hls 인덱스 파일 호환성 강화
버그수정
- 정상적인 Handshake없이 암/복호화가 진행되면 비정상 종료되던 증상
- ACL이 활성화된 상태에서 간헐적으로 비정상 종료되던 증상
2.3.1 (2016.02.25)¶
- MP3를 mp3-hls 로 전송한다.
기능개선/정책변경
- 사용자정의 Access 로그포맷 추가 | %y 요청 HTTP 헤더 크기 | %z 응답 HTTP 헤더 크기
버그수정
- WM - Dest 포트를 입력하지 않으면 설정되지 않던 증상
2.3.0 (2016.02.03)¶
- 컨텐츠를 handling-http-requests-compression 하여 전송한다.
버그수정
- expires 헤더 시간을 Modification으로 설정한 경우 max-age 값이 잘못 계산되던 증상
- dims - 평균 통계 산출할 때 분모를 “성공” 횟수만 사용하던 증상
v2.2.x¶
2.2.5 (2016.01.12)¶
기능개선/정책변경
- HTTP <451 Unavailable For Legal Reasons> 응답코드 추가
버그수정
- TLS - 공격성 패킷에 비정상 종료되던 증상 (예외처리 강화)
2.2.2 (2015.12.04)¶
- 원본으로 보내는 HTTP요청의 헤더를 :ref:`origin-modify-client`한다.
기능개선/정책변경
- handling-http-requests-modify-client - put액션 추가. 같은 이름의 헤더를 멀티라인으로 삽입한다.
2.2.1 (2015.11.19)¶
버그수정
- TLS - Handshake과정 중 클라이언트가 ChangeCipherSpec과 ClientFinished을 따로 보낼 때, 서버가 ChangeCipherSpec을 중복해서 보내던 증상
- DIMS - Animated GIF를 리사이즈할 때 비율이 유지되지 않던 증상
2.2.0 (2015.11.04)¶
- TLS 1.2를 지원한다. (+Forward Secrecy등 세세한 보안정책 강화)
버그수정
- 디스크 정보를 얻지 못한 경우 비정상 종료되던 증상
- TLS - Handshake과정에서 Max버전을 선택하지 않던 증상 | Before. TLSPlaintext.version 사용 | After. ClientHello.client_version 사용
v2.1.x¶
2.1.7 (2015.10.07)¶
- multi-trimming - 시간 값을 기준으로 복수로 지정된 구간을 하나의 영상으로 추출한다.
기능개선/정책변경
- access - X-Forwarded-For헤더 기록옵션에 TrimCIP추가
버그수정
- hls-http-live-streaming - 일부 profile에서의 화면떨림 증상
- dims - TTL이 0으로 설정되어 있을 때 간헐적으로 500 Internal Error로 응답하던 증상
- X-Forwarded-For 헤더를 로그에 c-ip필드로 기록할 때 공백 문자가 포함되던 증상
2.1.6 (2015.09.10)¶
기능개선/정책변경
- dims - animated-gif 에 대해 첫 장면만 변환할 수 있다.
버그수정
- 15장. 접근제어 - IP허용/차단이 정상동작하지 않던 증상
- dims - Crop등에서 + 기호를 이용한 좌표지정이 되지 않던 증상
2.1.5 (2015.08.18)¶
- sub-path - 접근 경로에 따라 다른 가상호스트로 분기한다.
- facade - 접근 도메인에 따라 클라이언트 트래픽 통계와 Access로그를 분리한다.
2.1.4 (2015.07.31)¶
기능개선/정책변경
- CPU사용량 개선
- multi-nic - NIC이름으로 Listen한다.
- 접근제어 시점 변경 | Before. 클라이언트가 요청한 URI에서 키워드(DIMS나 MP4HLS등) 제거 후 검사 | After. 클라이언트가 요청한 URI 그대로 검사
버그수정
- dims - 인코딩된 변환 문자열을 인식하지 못하던 증상
- hardpurge 가 대소문자 구분 구분 정책을 따르지 않던 증상
- 설정백업할 때 post 이 누락되던 증상
2.1.3 (2015.06.25)¶
기능개선/정책변경
- syncstale - 관리(purge, expire, hardpurge) API호출이 인덱싱에 반영되지 않는 경우가 없도록 로그로 기록하여 서비스 재가동시 다시 반영한다.
- 사용자정의 Access 로그포맷 에 %u표현 추가. 클라이언트가 요청한 Full URI를 기록한다.
버그수정
- dims - 원본서버에서 Last-Modified헤더를 주지 않을 때 이미지가 갱신되지 않던 증상
- trimming 된 MP4의 크기가 4GB를 넘어갈 때 CPU를 과점유하던 증상
- 에러 페이지를 응답할 때 via 헤더 설정이 반영되지 않던 증상
2.1.2 (2015.05.29)¶
- WM - 영문버전 지원
기능개선/정책변경
- Single Core 장비 지원
버그수정
- adv-topics-indexing 모드에서 커스터마이징 모듈이 오동작하던 증상
2.1.1 (2015.05.07)¶
- has-http-live-streaming - Stream Alternates형식을 통해 Bandwidth, Resolution 정보를 제공한다.
버그수정
- 헤더가 깨진 MP4영상 분석 중 비정상 종료되던 증상
2.1.0 (2015.04.15)¶
- adv-topics-indexing 모드 추가.
- dims 에서 Animated GIF포맷을 지원한다.
- dims 변환 통계추가
기능개선/정책변경
- 5장. Caching 무효화 에서 디렉토리 표현 제거 | 디렉토리 표현(example.com/img/)은 해당 URL에 해당하는 (원본서버가 응답한)파일 하나만을 의미한다. | 기존의 디렉토리 표현(example.com/img/)은 패턴(example.com/img/*)으로 통합한다.
- API표현 추가 | /monitoring/average.xml | /monitoring/average.json | /monitoring/realtime.xml | /monitoring/realtime.json | /monitoring/fileinfo.json | /monitoring/hwinfo.json | /monitoring/cpuinfo.json | /monitoring/vhostslist.json | /monitoring/geoiplist.json | /monitoring/ssl.json | /monitoring/cacheresource.json | /monitoring/origin.json | /monitoring/coldfiledist.json
- WM - resolv.conf 편집기능 삭제
v2.0.x¶
2.0.7 (2015.06.25)¶
버그수정
- media_dims - 원본서버에서 Last-Modified헤더를 주지 않을 때 이미지가 갱신되지 않던 증상
- trimming 된 MP4의 크기가 4GB를 넘어갈 때 CPU를 과점유하던 증상
- 에러 페이지를 응답할 때 via 헤더 설정이 반영되지 않던 증상
2.0.5 (2014.04.01)¶
기능개선/정책변경
- trimming 된 영상을 hls-http-live-streaming 로 서비스할 수 있다. 다음은 원본영상(/vod.mp4)의 0~60초 구간을 Trimming한 뒤 hls-http-live-streaming 로 서비스하는 표현이다. | /vod.mp4?start=0&end=60/mp4hls/index.m3u8 | /vod.mp4**/mp4hls/index.m3u8**?start=0&end=60 | /vod.mp4?start=0/mp4hls/index.m3u8?end=60
- hls-http-live-streaming 인덱스 파일(.m3u8) 버전 개선 | Before. 버전 1 | After. 버전 3 (버전 1로 변경 가능)
버그수정
- hls-http-live-streaming 변환 중 HTTP인코딩되는 특수문자가 있을 때 비정상 종료되던 증상
- 헤더가 깨진 MP4영상 분석 중 CPU가 과도하게 점유되던 증상
- Audio의 KeyFrame이 균일하지 않은 MP4영상을 hls-http-live-streaming 로 서비스할 때 Audio와 Video의 동기가 안맞는 증상
- RRD - 통계수집이 되지 않던 증상, 응답시간이 평균이 아니라 합으로 표시되던 증상
- WM - 신규 디스크 투입시 포맷을 강제하던 조건 제거
2.0.4 (2015.02.27)¶
기능개선/정책변경
- 원본 선택 의 Hash 알고리즘 변경 | Before. hash(URL) / 서버대수 | After. Consistent Hashing <http://en.wikipedia.org/wiki/Consistent_hashing>
- 가상호스트 접근제어 를 통해 Redirect 할 때 클라이언트가 요청한 URI을 파라미터로 입력할 수 있다.
버그수정
- 캐싱된 파일이 삭제되지 않아 디스크가 꽉 차던 증상
2.0.3 (2015.02.09)¶
기능개선/정책변경
- DIMS 내재화 및 고도화
- WM - 트래픽 관련 안내 메세지 추가
버그수정
- WM - 신규 가상호스트 생성이 실패 하는 버그 수정
2.0.2 (2015.01.28)¶
- 원본서버에 캐싱요청할 때 클라이언트가 보낸 User-Agent헤더 값을 보낼 수 있다.
버그수정
- MDAT 길이가 1인 MP4파일의 Trimming이 되지 않던 증상
- WM - 클러스터 내의 다른 서버 그래프가 표시되지 않던 증상
- WM - 클러스터 내의 다른 서버들이 현재 서버로 보여지던 증상
2.0.1 (2014.12.30)¶
- HitRatio그래프가 0으로 표시되던 증상
2.0.0 (2014.12.17)¶
- 원본에서 다운로드된 크기만큼만 디스크 공간사용. (origin-partsize 참조)
- 메모리 제한 기능추가.
- TLS 1.1 지원.
- AES-NI를 통해 SSL/TLS 가속 지원.
- ECDHE 계열의 CipherSuite를 지원. (CipherSuite 선택 참조)
- DNS 로그 추가
- 원본서버가 Domain일 경우 각 IP별 TTL을 사용하도록 정책변경.
- 원본 장애감지와 복구 추가
- 원본 Health-Checker 추가
- 시스템 Free 메모리 추가
- 기타 | 최소 실행환경 변경. (Cent 6.2이상, Ubuntu 10.01 이상) | 설치 패키지에 NSCD데몬이 탑재. | DIMS 기본 탑재. | Caching 초기화 후 STON 재시작하도록 변경. | <DNSBackup> 기능 삭제 | <MaxFileCount> 기능 삭제. | <Distribution> 기능 삭제. 원본 선택 기능에 통합.
v1.4.x¶
1.4.2 (2014.12.08)¶
- Purge(자동 복구) API가 HardPurge(복구 불가)로 동작하도록 purge 할 수 있다.
- 로그 롤링시 압축하도록 id1 할 수 있다.
- FTP 클라이언트 기능강화 - 전송시간, 경로, 삭제, 백업 기능 추가
버그수정
- SSL/TLS Handshake과정 중 비정상 종료되던 증상
1.4.1 (2014.11.25)¶
- 클라이언트가 보낸 URI를 가공없이 원본서버에 보내도록 클라이언트 요청 유지 할 수 있다.
버그수정
- MP4영상에 SPS/PPS가 없을 때 비정상 종료되던 증상
- FTP 클라이언트가 Active모드로 동작하지 않던 증상
- WM - SNMP의 VhostMin, ViewMin을 0부터 설정가능하도록 수정 (기존 1부터)
v1.3.x¶
1.3.20 (2014.11.05)¶
- [전역] id5 기능 추가. 설정된 최대 클라이언트(소켓) 수를 넘어가는 접근이 발생할 경우 클라이언트 접속 즉시 연결을 끊는다. 이는 솔루션과 플랫폼을 보호하기 위한 가장 강력한 조치이다. 전체 소켓이 일정비율 이하로 내려가면 다시 클라이언트 접근을 허용한다.
- 9장. HTTPS 프로토콜(SSL3.0 또는 TLS1.0) 선택가능
기능개선/정책변경
- file-system 에서 파일시간 제공방식 설정가능 | Before. 로컬에 캐싱된 시간 | After. 원본의 Last-Modified 시간
- id5 ON 설정시 동작변경 | Before. cookie 헤더를 제거한다. | After. cookie, set-cookie, set-cookie2 헤더를 제거한다. WM에서 경고메시지 강화
- WM - 가상호스트 삭제시 삭제 될 가상호스트 이름 명시
- WM - 설치시 cgi-bin경로에 어떤 파일도 설치하지 않도록 수정
- WM - RRD 메모리 그래프의 Scale을 1000에서 1024로 변경
버그수정
- file-system 에서 파일접근에 실패했을 경우 비정상종료될 수 있던 증상
- WM - origin-exclusion-and-recovery 에서 Cycle과 값이 서로 바뀌어서 저장되던 증상
1.3.19 (2014.10.21)¶
기능개선/정책변경
- trimming 정책변경 | Before. 모든 트랙을 Trimming한다. | After. Audio/Video 트랙만을 Trimming한다. AllTracks속성을 통해 기존처럼 모든 트랙을 Trimming할 수 있다.
1.3.18 (2014.10.15)¶
버그수정
- dims 처리에서 클라이언트가 보낸 QueryString이 반영되지 않던 증상
- 원본서버가 모두 배제되었을 때 특정조건에서 캐싱파일이 초기화되지 않던 증상
- WM - 보안정책 강화 및 가상호스트 이름에 공백이 없도록 Trim.
- WM - Unmount된 디스크의 상태를 올바르게 인식하지 못하던 증상
1.3.17 (2014.09.22)¶
버그수정
- SNMPWalk를 통해 cache-host-traffic-filesystem 통계가 제공되지 않던 증상
- WM을 통해 DIMS설정 시 해당 가상호스트의 찾기 가 초기화되던 증상
1.3.14 (2014.08.13)¶
- 최대 사용 메모리를 제한하도록 메모리 제한 할 수 있다.
- SNMP - 허가된 Community외엔 접근이 불가능하도록 community 할 수 있다.
- WM - 서비스 Listen포트를 멀티로 설정할 수 있다. 클러스터 전용포트를 설정할 수 있다.
기능개선/정책변경
- 파일 인덱싱 정책 변경 | Before. 완료된 파일만 인덱싱한다. | After. 다운로드 중인 파일도 인덱싱한다.
- emergency 기본 값 OFF로 변경
- 기본 Access로그에 sc-content-length필드 추가
1.3.12 (2014.07.10)¶
기능개선/정책변경
- acl, 8장. 바이패스, id2 - 복합조건을 설정할 때 결합(AND) 키워드를 “&”에서 ” & “로 변경. | Before. $IP[AP]&!HEADER[referer] 표현가능 | After. $IP[AP] & !HEADER[referer] 처럼 결합조건 사이에 반드시 공백필요
- SNMP - bytesHitRatio 타입이 음수를 표현할 수 있도록 gauge32에서 integer로 변경
- WM - 비대칭키 인증정책으로 변경
버그수정
- 1MB보다 작은 MP4파일을 17장. 미디어 기능으로 서비스할 때 오동작하거나 비정상 종료되던 문제
- 비정상 HTTP요청에 대한 예외처리 강화
1.3.11 (2014.06.19)¶
- 마지막(=현재) 설정상태 확인(/conf/lastest) API 추가
기능개선/정책변경
- 8장. 바이패스 개선 | Before. 명시적인 URL 또는 Cookie등으로 바이패스(또는 예외) 설정 | After. IP, Header, URL 또는 이를 결합한 복합조건으로 바이패스 가능. Cookie바이패스 삭제.
- 클라이언트 트래픽 - 디렉토리 별 requestHitRaio 추가
- WM - hostname과 IP가 로그인하지 않은 상태에서 표시되지 않도록 수정
버그수정
- DNS가 Resolving응답을 정상적으로 주지만 주소가 없을 때 죽는 버그.
- origin.log, filesystem.log 롤링할 때 파일명이 GMT시간으로 생성되던 증상. 로컬시간으로 생성되도록 수정.
- /monitoring/hwinfo API에서 디스크 사용량이 표시되지 않던 증상
- WM - 마지막 접근시간이 올바르게 표시되지 않던 증상
1.3.10 (2014.06.03)¶
- 모든 Disk가 장애로 배제되었을 때 동작방식(재투입, Bypass, 종료)을 storage 할 수 있습니다.
- 원본 HTTP요청의 Host헤더를 클라이언트가 보낸 값을 사용하도록 설정할 수 있습니다.
기능개선/정책변경
- 파일캐싱 모니터링에서 QueryString 특수문자을 포함하는 URL도 모니터링할 수 있습니다.
- 10장. 모니터링 & 통계 에서 5분간 총 양이 함께 표기됩니다.
- HTTP POST요청캐싱과 Bypass정책이 동시에 설정된 경우, 서비스 정책이 재정립되었습니다
- Trimming정책 변경 | Before. Trimming의 끝(end) 시간에 가장 인접하도록 분할 | After. Trimming의 끝(end) 시간의 이전 Key-Frame으로 분할
버그수정
- MP4파일이 서비스되지 않고 CPU를 점유하던 증상
1.3.9 (2014.05.21)¶
기능개선/정책변경
- 서비스 거부 조건에서 응답코드를 acl 할 수 있습니다. | Before. 에러 페이지에 “401 Access Denied”라고 명시 | After. 별도의 페이지 없이 설정된 응답코드로만 응답
버그수정
- 잘못된 MP4영상 trimming 중 비정상 종료되던 증상.
- 18장. File System 에서 (최초 :ref:`range`가 설정된 상태에서 캐싱되는 파일에 대해) 간헐적으로 잘못된 데이터를 서비스하던 증상.
- WM - Port바이패스 설정이 반영되지 않던 증상
1.3.8 (2014.04.30)¶
버그수정
- hls-http-live-streaming 변환 중 비디오가 깨지던 증상.
- 강제로 TTL을 만료시킨 컨텐츠가 304 Not Modified로 인해 TTL이 다시 정해질 때 설정상 가장 큰 값이 할당되던 증상. 설정상 가장 작은 값이 할당되도록 수정.
1.3.7 (2014.04.11)¶
버그수정
- domain.com:80 처럼 Port가 명시된 HTTP요청에 대해 가상호스트를 찾지 못하던 증상 (v1.3.4~1.3.6)
- 잘못된 MP4영상분석 중 비정상 종료되던 증상
1.3.6 (2014.04.09)¶
기능개선/정책변경
- admin-log | Before. 시간 또는 크기 중 택1 | After. 시간과 크기 동시설정 가능
- WM - 페이지 상단에 서버의 호스트명과 IP를 보여줍니다.
버그수정
- WM - 설정파일 중 CDATA로 저장된 문자열이 Plain Text로 바뀌던 증상
1.3.4 (2014.03.26)¶
버그수정
- (FileSystem이 Mount되어 있을 때) STON의 정상종료가 오래 걸리던 증상
- WM - (FileSystem을 사용하지 않는 환경에서) 신규 가상호스트 추가시 FileSystem페이지 활성화되던 증상
- WM - 클러스터링 구성 중 대상 WM이 한번도 실행되지 않았었다면 설정이 적용되지 않던 증상
1.3.2 (2014.03.05)¶
버그수정
- 불완전한(=실시간으로 변환 중인) MP4 파일 캐싱 중 서비스가 멈추던 증상.
- WM에서 클러스터 전체 적용 시 가상호스트 파일이 초기화되던 증상
1.3.0 (2014.02.20)¶
- 18장. File System 추가 - STON을 Linux VFS(Virtual File System)에 Mount합니다. 원본서버의 모든 파일을 로컬 파일 I/O로 사용할 수 있습니다.
- caching 추가 - 설정이 변경될 때마다 전체설정을 기록합니다. API(목록, 롤백, 다운로드, 업로드)와 :ref:`meta`SNMP를 통해 열람, 다운로드, 업로드, 복원이 가능합니다.
- has-http-live-streaming 추가 - 단일 MP4파일을 HLS(Http Live Streaming)으로 전송할 수 있습니다.
- 통계 추가 - 전송 중 원본서버에서 먼저 소켓을 종료시킨 횟수
기능개선/정책변경
- 변수 | Before. 가상호스트가 삭제되거나 순서가 변경될 경우 [vhostIndex]가 재조정된다. 예를 들어 A(1), B(2), C(3)에서 B가 삭제된 경우 A(1), C(2)로 재조정된다. | After. [vhostIndex]를 기억한다. 예를 들어 A(1), B(2), C(3)에서 B가 삭제되더라도 A(1), C(3)을 유지한다. 신규 가상호스트가 추가되면 비어있는 [vhostIndex]를 가진다. 예를 들어 가상호스트 D가 추가되면 A(1), D(2), C(3)로 재조정된다.
- 설정 리로드 API 변경 | Before. /conf/reloadall, /conf/reloadserver, /conf/reloadvhosts가 별도로 존재하며 기능을 달리한다. | After. /conf/reload로 일괄통일한다. 하위 호환성을 위해 기존 API를 유지한다.
v1.2.x¶
1.2.14 (2014.02.06)¶
기능개선/정책변경
- 원본주소 DNS 정책 변경 | Before. 다른 가상호스트지만 원본주소로 같은 Domain을 사용한다면 Domain Resolving결과를 공유한다. | After. 모든 가상호스트는 독립적으로 Domain Resolving을 수행하며 공유하지 않는다.
버그수정
- WM을 통한 Disk Hot-Swap 오동작 수정.
1.2.13 (2014.01.22)¶
버그수정
- 특정 설정(no-cache-ttl`=ON, :ref:`caching-policy-renew`=ON, :ref:`vary 존재)에서 응답이 지연되거나 전송되지 않던 동작 수정.
1.2.12 (2014.01.02)¶
버그수정
- 최신 NEXUS 기기에서 Trimming된 MP4/M4A가 재생되지 않던 증상 수정. (에러 메세지: The player doesn’t support this type of audio file.)
1.2.11 (2013.12.20)¶
기능개선/정책변경
- 원본서버 Cache-Control 헤더 인식정책 변경 | Before. no-cache 또는 max-age만을 인식한다. | After. no-cache, no-store, no-transform, must-revalidate, proxy-revalidate, private, max-age를 구분하여 인식한다. custom은 무시한다.
- 5분 평균 Request Hit율 계산방식 변경 | Before. 각 TCP_XXX의 (단위 시간에 대한)평균을 구한 뒤 Hit율 계산한다. 각 평균 값이 단위 시간보다 작을 때 누락될 수 있다. | After. (평균을 내지 않고) 비율로만 계산하여 값이 누락되지 않는다.
1.2.10 (2013.12.13)¶
기능개선/정책변경
- HTTPS 통신에서 Access로그 범위 변경 | Before. 클라이언트가 SSL Server Finished 패킷을 온전히 수신한 HTTPS 트랜잭션만을 Access로그에 기록한다. | After. 클라이언트가 SSL Server Finished 패킷을 온전히 수신하지 못했더라도 HTTP Request 패킷을 보냈다면 Access로그에 기록한다.
버그수정
- 비정상 종료(물리적 세션 손실)된 HTTPS세션이 재사용될 때 이전에 요청되었던 컨텐츠와 현재 요청된 컨텐츠를 동시에 처리하던 증상. 2개의 HTTP 요청이 동시에 처리될 수 있었으며 이를 항상 현재 요청한 요청만이 유효하도록 수정.
1.2.9 (2013.12.09)¶
기능개선/정책변경
- bandwidth-throttling | Before. Boost 시간동안 미디어를 전송할 때 헤더를 포함한다. 헤더가 클 경우 미디어 데이터가 전송되지 않아 버퍼링이 발생할 수 있다. | After. 미디어 헤더는 대역폭 제한없이 전송한다. 헤더 전송이 완료된 후 Boost 시간이 시작된다.
버그수정
- WM 포트 변경 후 STON 업데이트 시 변경된 포트가 유지되지 않던 증상
1.2.8 (2013.11.14)¶
기능개선/정책변경
- 접속하는 HTTP 클라이언트마다 고유번호(session-id)를 부여합니다. session-id는 Access로그와 Origin로그에 추가되어 연관성을 유추할 수 있습니다.
- API호출의 파라미터로 https://... 형식을 인식합니다.
버그수정
- :ref:`id5`가 ON으로 설정되어 있을 때 Content-Disposition헤더가 HTTP 응답에 2번 표시되던 증상
- Bandwidth-Throttling설정이 OFF일 때 Trimming이 동작하지 않던 증상
- WM계정에 특수문자(&)사용시 로그인 안되던 증상
1.2.5 (2013.10.10)¶
- Origin By Client를 설정할 수 있습니다.
기능개선/정책변경
- 인식할 수 있는 미디어파일에 대해 동적으로 Bandwidth-Throttling의 Bandwidth를 :ref:`bandwidth-throttling`할 수 있습니다. v1.2.4까지 존재했던 Media.Pacing은 이 기능에 포함되면서 삭제되었습니다.
버그수정
- 극히 드물게 잘못된 문자열 참조 오류로 인해 비정상종료되던 증상
1.2.4 (2013.09.27)¶
- Bandwidth-Throttling을 통해 전송 대역폭을 다양하게 :ref:`bandwidth-throttling`할 수 있습니다. | Warning: 다음 버전에서 Media.Pacing은 :ref:`bandwidth-throttling`에 통합될 것입니다. 미디어 파일(현재 MP3, MP4, M4A 지원)의 Bitrate를 :ref:`bandwidth-throttling`에서 인식할 수 있는 형태가 될 것입니다. 현재는 기존 기능인 Media.Pacing이 더 우선하도록 개발되어 있습니다.
- 가상호스트별로 클라이언트 최대 Bandwidth를 제한하도록 :ref:`id1`할 수 있습니다.
- 헤더가 뒤에 있는 M4A파일을 헤더를 앞으로 옮겨서 서비스하도록 :ref:`mp4-m4a`할 수 있습니다.
- M4A파일을 원하는 구간만큼 잘라내어 서비스하도록 :ref:`trimming`할 수 있습니다.
기능개선/정책변경
버그수정
- 클러스터가 구성되지 않던 증상 - IP를 추출할 때 Loopback이 추출되던 증상
1.2.3 (2013.09.05)¶
기능개선/정책변경
- 원본세션을 재사용하지 않도록 :ref:`id8`할 수 있습니다.
버그수정
- MP4 Trimming 중 비정상 종료되던 증상
- 콘솔에서 수정한 가상호스트 설정이 WM의 클러스터에 반영되지 않던 증상
1.2.2 (2013.08.16)¶
기능개선/정책변경
- 서비스 허용/차단 조건에 부정(!IP, !HEADER, !URL)조건이 :ref:`acl`되었습니다.
- WM과 콘솔에서 동시에 설정을 변경할 때 WM에서 콘솔에서 변경한 내용을 인식하도록 변경되었습니다.
- WM에서 IE의 “호환성 보기” 메뉴를 숨기도록 변경되었습니다.
버그수정
- CPU 과부하 상태에서 바이패스 세션이 정상적으로 정리되지 않아 비정상 종료되던 증상
- (vary 설정환경에서) 원본서버에서 200 OK로 응답하지 않는 컨텐츠 서비스 중 비정상 종료되던 증상
- 가상호스트명과 Alias가 같은 경우 Alias를 제거했을 때 가상호스트를 찾을 수 없던 증상
- WM 클러스터에 설정이 반영되지 않던 증상
1.2.1 (2013.07.26)¶
버그수정
- WM에서 클러스터가 구성되지 않던 증상
- 로그설정 변경 후 “/conf/reloadserver” API를 호출했을 때 반영되지 않던 증상
- SNMP에서 Host평균 통계가 평균이 아닌 합으로 계산되던 증상
- 특정 상황에서 클라이언트 트래픽 통계수치가 비정상적으로 높게 계산되던 증상
1.2.0 (2013.07.01)¶
- :ref:`wm`이 추가되었습니다. 모든 설정이 WM을 통해 가능하며 MRTG(5종류 - 대쉬보드/5분/30분/2시간/1일)가 최대 18개월치 제공됩니다. WM을 통해 STON을 클러스터로 묶어서 쉽게 관리할 수 있습니다.
- Graph API가 추가되었습니다.
- 원본서버의 Vary헤더를 인식하도록 :ref:`vary`할 수 있습니다.
- 클라이언트와 통신하는 HTTP 요청/응답 헤더를 변경하도록 :ref:`id4`할 수 있습니다.
- 원본서버의 모든 헤더를 클라이언트에게 전달하도록 :ref:`id5`할 수 있습니다.
- 원본서버에서 Redirect된 컨텐츠를 추적하여 캐싱하도록 :ref:`redirect`할 수 있습니다.
- 특정 URL에 대해서만 QueryString을 인식 또는 무시 하도록 :ref:`querystring`할 수 있습니다.
- 매니저 포트 ACL마다 접근권한을 :ref:`env-host`할 수 있습니다.
- 로그를 ON/OFF하도록 :ref:`admin-log`할 수 있습니다.
- 로컬통신의 로그를 기록하지 않도록 :ref:`admin-log`할 수 있습니다.
- 로컬통신의 통계를 수집하지 않도록 :ref:`id2`할 수 있습니다.
기능개선/정책변경
- 로그 Trace접근이 있을 때 로그에 기록합니다.
- 하드웨어 정보를 조회할 때 CPU를 높게 사용하던 증상이 개선되었습니다.
v1.1.x¶
1.1.17 (2013.05.27)¶
- Origin By Client를 설정할 수 있습니다.
기능개선/정책변경
- Transfer-Encoding으로 전송된 컨텐츠를 (전송지연 등의 이유로) 온전하게 캐싱하지 못한 경우 클라이언트 서비스정책 변경 | Before. 캐싱에 실패한 현재 컨텐츠를 서비스 | After. 이전에 온전하게 캐싱된 컨텐츠가 있다면 이전 컨텐츠로 서비스. 없다면 500 Internal Error.
버그수정
- RefreshExpired가 OFF인 상태에서 PartSize가 0보다 크게 설정된 경우 컨텐츠 갱신이 안되는 증상
1.1.16 (2013.05.15)¶
기능개선/정책변경
- 리눅스 최대 파일개수 제한으로 File I/O가 실패하지 않도록 파일저장방식 변경
- 정상동작을 위해 필요한 서브파일 점검 로그 추가
버그수정
- 갱신중인 파일이 HardPurge될 때 비정상 종료되던 증상
- 가상호스트별로 미디어 설정이 되지 않던 증상
- syslog 설정이 리로드되지 않던 증상
- OriginError로그에 syslog설정시 Info로그에 Inactive로 표시되던 증상
1.1.15 (2013.04.29)¶
- CPU 성능지표(Nice, IOWait, IRQ, SoftIRQ, Steal) 통계 추가 - system, :ref:`system`(System.27 ~ 36)
버그수정
- Track정보가 많은 MP4파일 분석 중 비정상 종료되던 증상
- HTTP Transfer-Encoding된 컨텐츠를 전송할 때 지연되던 증상
1.1.14 (2013.04.10)¶
- SNMP에 :ref:`cache-host`(=전체 가상호스트의 합)가 추가되었습니다.
기능개선/정책변경
- (파일이 없을 때) GeoIP파일목록 조회 결과 변경 | Before. 404 NOT FOUND | After. 200 OK (“files”: [] 응답)
버그수정
- SSLv3에서 RSA_WITH_3DES_EDE_CBC_SHA로 Handshake가 되지 않던 증상 수정
- :ref:`https`속성에 빈 문자열 입력 시 오동작하던 증상
1.1.13 (2013.03.29)¶
버그수정
- 디렉토리별 통계가 설정된 상태에서 누적통계가 OFF인 경우 비정상 종료되던 증상
- 처음 접근되는 컨텐츠가 원본서버로부터 응답을 받기 전에 Purge되는 경우 클라이언트에게 응답을 주지 않던 증상
- HTTP 요청의 URI가 상대주소가 아니라 절대주소일 경우 서비스 안되던 증상
1.1.12 (2013.03.27)¶
- No-Cache요청이 올 경우 요청된 컨텐츠를 즉시 만료시키도록 :ref:`no-cache-ttl`할 수 있습니다.
- CentOS 패키지로 openSUSE에서 설치할 수 있습니다.
기능개선/정책변경
- No-Cache요청 인식조건 변경 | Before. “pragma: no-cache” 또는 “cache-control: no-cache” | After. 기존 조건에 “cache-control: max-age=0” 추가
버그수정
- DNS갱신시 비정상 종료되던 증상
- 최대 파일개수를 넘어갈 때 URL에 Vertical Bar(|)가 있는 파일들이 삭제되지 않던 증상
- HTTP 요청이 바이패스 될 때 HttpReqBodySize와 ClientInbound 값이 정확하지 않던 증상
1.1.11 (2013.03.21)¶
기능개선/정책변경
- 원본서버 장애코드 변경 | Before. 숫자로 표시 | After. 읽기 쉬운 형식으로 표시(Connect-Timeout, Receive-Timeout, Server-Close)
- 원본서버 장애로그 기록시 주석으로 에러상황을 기록하던 것 제거. OriginErrorLog로 통합.
버그수정
- Manager Port변경 후 Reload할 때 비정상 종료되던 버그 수정
1.1.10 (2013.03.07)¶
- 가상호스트마다 접근/차단조건(IP, GeoIP, URI, Header)을 :ref:`access-control-vhost`할 수 있습니다. 관련 통계가 추가되었습니다.
- 도메인 Resolving이 실패할 경우 최근 사용된 IP들을 모두 사용하여 원본서버 부하를 분산하도록 설정할 수 있습니다.
- 모니터링 API가 추가되었습니다. | 가상호스트 목록 조회 | 하드웨어 정보 조회 | HTTPS CipherSuite 조회 | 접근차단 조건(acl.txt) 조회 | Expires헤더 조건(expires.txt) 조회
기능개선/정책변경
- 로그 디스크 여유공간이 부족해질 경우 정책 변경 | Before. 개입하지 않음. 관리자가 명시적으로 삭제해야 함. | After. Access로그만을 삭제. 만약 현재 사용 중인 로그를 지워야하는 상황이라면 새로운 로그 생성 후 삭제함.
- STON 종료 후 (vhosts.xml에서)삭제된 가상호스트 파일들에 대한 정책 변경 | Before. 개입하지 않음. 관리자가 명시적으로 삭제해야 함. | After. 디스크 여유공간이 부족해지면 우선적으로 삭제.
- (가상호스트 별) 재구동 시 정상적으로 로딩되지 않은 디스크의 파일들에 대한 정책 변경 | Before. 서비스 중 자연히 덮어씌워지도록 남겨둠 | After. 해당 디스크를 신뢰할 수 없다고 판단하여 모두 무효화. 클린업 시간 또는 디스크 여유공간 부족 시점에 모두 삭제.
- 도메인 Resolving결과 조회 API 변경. | Before. /dns/list | After. /monitoring/dnslist
- 로그 트레이스 API 변경 | Before. /logtrace/... | After. /monitoring/logtrace/...
- 도메인 Resolving결과에 백업된 IP목록 추가
1.1.9 (2013.02.27)¶
- :ref:`httpd.apache.org/docs/2.2/mod/mod_expires.html`와 같이 Expires헤더를 :ref:`expires`할 수 있습니다.
- HTTPS의 CipherSuite를 :ref:`https`할 수 있습니다.
- 파일을 관리(Purge/Expire/HardPurge/ExpireAfter)할 때 단일 URL만 입력하여도 QueryString까지 모두 관리하도록 :ref:`querystring`할 수 있습니다.
- ETag헤더 표시여부를 :ref:`etag`할 수 있습니다.
- Age헤더 표시여부를 :ref:`age`할 수 있습니다.
기능개선/정책변경
- HTTPS CipherSuite가 추가되었습니다. | RSA_WITH_RC4_MD5 | TLS_RSA_WITH_3DES_EDE_CBC_SHA
- 숫자(초=sec)로만 하던 표현을 인식하기 쉬운 문자형식으로 표현가능 | Before. /image/ad.jpg, 1800 | After. /image/ad.jpg, 6 hours
- SNMP에서 평균으로만 제공하던 수치를 누적으로 제공 (클라이언트/원본) | 기존에 Count라는 표현을 Average로 변경. Average는 시간으로 나눈 평균을 의미 | 시간동안 집계된 전체 수는 Count로 표현 | 전체 요청/응답 개수 추가 | 응답코드별 응답/완료 개수 추가 | Request Hit Count 추가
- 재시작/종료/캐시초기화 API를 호출할 때 “확인” 과정없이 호출할 수 있습니다.
- 시스템 Load Average - 1분/5분/15분 통계추가
- 모든 가상호스트의 원본서버를 초기화 할 수 있습니다.
버그수정
- Domain Resolving결과가 변경되었을 때 여러 가상호스트에 동시에 반영이 안되던 버그 수정
- Purge/Expire에서 QueryString이 붙어있는 URL이 처리안되던 버그 수정
1.1.8 (2013.02.21)¶
기능개선/정책변경
- Origin 로그강화 | 접속한 포트 기록 | Bypass와 PrivateBypass구분 가능 | 원본서버가 보낸 Content-Encoding 헤더 기록
- Access 로그강화 | 클라이언트가 보낸 Accept-Encoding헤더 기록 | Bypass와 PrivateBypass구분 가능
- 원본서버가 도메인명으로 설정되어 있을 때 기능개선 | Resolving결과가 즉시 반영. | IP들에 대하여 개별로 배제/복구.
- Purge/Expire/HardPurge/ExpireAfter 호출결과 응답코드 수정 | 정상. 200 OK | 가상호스트 없음. 502 BAD GATEWAY | 잘못된 규격. 400 BAD REQUEST
- FAQ페이지 업데이트 | 원본서버 사용/배제/복구 정책은? | 디스크 여유공간은 어떻게 보장되나요?
버그수정
- 디스크 공간이 부족해도 공간확보가 되지 않던 버그 수정
1.1.7 (2013.02.16)¶
기능개선/정책변경
- Cent OS 5.5이상과 Ubuntu 10이상에서 동시접속 소켓이 10만을 넘으면 시스템 성능이 저하되며 소켓처리가 실패되는 증상을 확인하였습니다. 그러므로 최대 소켓을 10만으로 제한합니다.
버그수정
- 사용 중인 소켓이 설정된 최대 소켓수를 넘어갔을 때 증설되지 않던 버그 수정
- Byte Hit Ratio결과가 부정확하게 표시되던 버그 수정
- 누적통계 XML에서 ClientSession이 2번 나오던 버그 수정. (ClientActiveSession으로 변경)
- “abc*”로 패턴 설정했을 경우 “abc”처럼 패턴부분이 빈 문자열에 대해 인식하지 못하던 버그 수정
1.1.6 (2013.01.30)¶
- 원본서버가 멀티로 구성되어 있을 때 항상 서버마다 동일하게 요청하도록 :ref:`origin-balancemode`한다.
기능개선/정책변경
- 원본서버 부하분산 정책이 Session에서 RoundRobin으로 변경되었습니다.
- 전역로그(Info, Deny, OriginError)를 시간으로 롤링시킨다. | Before. 크기로만 롤링가능(Size속성만 존재) | After. 시간/크기로 롤링가능 (Size속성 제거. Type, Unit속성 추가)
- 잘못된 형식 또는 존재하지 않는 가상호스트를 대상으로 Purge/Expire/ExpireAfter/HardPurge 호출시 응답코드 변경 | Before. 200 OK | After. 400 BAD REQUEST 또는 404 NOT FOUND
버그수정
- v1.1.5에서 원본서버 주소목록을 변경하고 리로드하였을 때 간헐적으로 비정상종료되던 증상
- 원본서버에서 트랜잭션 완료 횟수를 수집할 때 Content-Length가 0인 응답이 누락되던 증상
1.1.5 (2013.01.28)¶
- 클라이언트마다 바이패스 전용세션을 사용하도록 :ref:`get-post`합니다. GET요청과 POST요청을 별도로 설정할 수 있습니다.
- 클라이언트 Cookie헤더에 따라 바이패스하도록 설정합니다.
기능개선/정책변경
- 원본서버 주소가 빠졌을 때 동작방식 변경 | Before. 이미 연결되어 있다면 재사용한다. | After. 즉시 재사용하지 않는다.
- :ref:`querystring`이 ON일 때 Purge/Expire동작방식 변경. | Before. 입력된 URL과 해당 URL에 QueryString이 붙은 컨텐츠 Purge/Expire | After. 입력된 URL만 Purge/Expire
- Active세션 산출방식 변경 | Before. 통계를 뽑는 시점에 데이터 전송이 이루어지고 있는 세션 | After. 데이터 전송이 발생한 Unique한 세션
- 통계/성능 데이터가 추가/삭제되었습니다. | system 통계 추가 | 종합통계에 요청회수, Active세션 통계 추가 | SSL클라이언트 세션 수 삭제
1.1.3 (2013.01.15)¶
기능개선/정책변경
- 한번에 기록할 수 있는 로그의 최대 크기를 10MB로 확장(이전: 2KB)
- POST로 보낼 수 있는 URL크기를 최대 1MB로 확장(이전: 10KB)
버그수정
- 로그가 시간기준으로 롤링될 때 파일명(날짜)이 정확하지 않던 증상
1.1.2 (2013.01.14)¶
기능개선/정책변경
- ETag헤더를 제공할 때 따옴표(”...”)로 묶어서 표기
- HIT율 계산식 변경 | Before. 즉시응답 / 모든응답 | After. (TCP_HIT + TCP_IMS_HIT + TCP_REFRESH_HIT + TCP_REF_FAIL_HIT + TCP_NEGATIVE_HIT) / 모든 응답
- 통계/성능 데이터가 추가/삭제되었습니다. | id9 추가 | 평균통계에 통계를 생성한 날짜/시간 추가 | 클라이언트에서 STON으로 접속/종료하는 system 수 추가 | STON이 원본서버로 접속/종료하는 system 수 추가 | system, system 추가 | system 추가 | “Cached” 통계 제거
- 정규표현식 성능향상 (X 20)
- fileinfo에서 미캐싱파일인 경우 status를 “OK”에서 “NOT_CACHED”로 변경”
버그수정
- SNMP에서 디스크정보(diskInfoPath, diskInfoStatus)를 얻을 때 Disk개수보다 큰 값이 diskIndex로 입력되면 비정상 종료되던 증상
- 디스크가 꽉 차기전에 삭제되지 않던 증상. 디스크 Available공간을 남은공간으로 이해하도록 수정
- stonapi가 관리포트를 인지하지 못하던 증상
- Info로그에 “Download-Range” 메시지 제거
1.1.1 (2012.12.24)¶
- 모든 가상호스트의 원본서버 이상동작을 하나의 파일(originerror)로 기록한다.
- HTTP Multi-Range요청을 처리할 수 있습니다.
- 원본서버에서 no-cache로 응답하더라도 클라이언트에게는 max-age를 주도록 :ref:`ttl-time-to-live`할 수 있습니다.
기능개선/정책변경
- Accept-Encoding처리 정책변경. | Before. 클라이언트와 원본서버의 압축이 호환되지 않으면 500에러로 응답한다. | After. 클라이언트와 원본서버의 압축이 호환되지 않더라도 원본서버의 응답을 보낸다.
- 다음과 같이 통계/성능 데이터가 추가되었습니다. | 원본/클라이언트 Active세션수가 추가되었습니다. | STON이 사용하는 CPU(Kernel, User) 성능수치가 추가되었습니다.
버그수정
- (설정: TTL=0, RefreshExpired=ON) 원본파일이 변경되었을 때 변경된 파일의 첫 응답코드를 500으로 보내던 증상
1.1.0 (2012.12.17)¶
- 가상호스트별로 최대 Outbound를 제한하도록 :ref:`id1`할 수 있습니다.
- 헤더가 뒤에 있는 MP4파일을 헤더를 앞으로 옮겨서 서비스하도록 :ref:`mp4-m4a`할 수 있습니다.
- MP4를 BiteRate만큼 낮은 대역폭으로 전송하도록 설정할 수 있습니다.
- 최대 서비스 파일개수를 설정할 수 있습니다.
- 최대 HTTP 세션 수를 :ref:`http`할 수 있습니다.
- API의 모든 함수를 리눅스 콘솔에서 호출할 수 있습니다.
- log-trace API를 통해 기록되는 로그를 실시간으로 받아볼 수 있습니다.
- 쉘에서 STON을 :ref:`getting-started-update`할 수 있습니다.
기능개선/정책변경
- 메모리 정책이 수정되었습니다. 최대 파일개수와 최대 소켓개수를 설정하여 컨텐츠 메모리크기를 조절할 수 있습니다. 자세한 내용은 :ref:`caching`를 참고하시기 바랍니다.
- 도메인을 리졸빙(Resolving)한 결과를 캐싱합니다. 최소 1초, 최대 10초동안 캐싱됩니다.
- OriginOptions의 일부설정(user-agent, host`Host, WL-Proxy-Client-IP, :ref:`xff-x-forwarded-for)을 바이패스되는 HTTP요청에 선택적으로 적용할 수 있습니다.
- 원본서버로부터 5xx계열의 응답코드가 캐싱된 경우 TTL이 만료되면 RefreshExpired가 OFF라도 항상 원본서버에서 갱신여부를 확인하고 서비스합니다.
- 원본서버에 example.com/dir1 처럼 디렉토리명을 같이 지정할 수 있습니다. 클라이언트가 /test.jpg로 요청한다면 원본서버로 요청하는 주소는 example.com/dir1/test.jpg가 됩니다.
- 갱신정책 설정의 기본 값이 OFF에서 ON으로 변경되었습니다.
- 파일캐싱 모니터링 항목이 강화되었습니다.
- 원본서버 주소가 도메인명이라면 별도로 <Host>를 설정하지 않아도 도메인 명으로 Host헤더를 보내도록 수정하였습니다.
- 다음과 같이 통계/성능 데이터가 추가되었습니다. | 원본/클라이언트 HTTP요청 개수가 통계에 추가되었습니다. | 정상적으로 완료된 원본/클라이언트 HTTP 트랜잭션의 통계가 추가되었습니다. | CPU와 Memory에 대한 통계가 추가되었습니다. | Disk별 성능지표가 추가되었습니다. | 원본로그에 cs-acceptencoding, sc-cachecontrol필드가 추가되었습니다.
버그수정
- 원본서버 배제/복구 과정(주소 3개 이상)에서 후순위의 원본서버가 우선 복구됐을 때 비정상 종료되던 증상
- HTTP 요청에서 헤더가 키와 값 사이에 공백이 없으면 해석하지 못하던 증상
- 로그를 “Size”로 설정했을 때 중간파일이 먼저 롤링되어 삭제되던 증상
- 다음 상황에서 응답을 주지 않던 증상 | A파일을 원본서버에 요청하였으나 404 Not Found가 발생 | Memory Swap과정 중 A파일의 Body를 Memory에서 삭제 (A파일은 Meta만 존재하는 상태가 됨) | A파일 서비스 요청이 들어옴 | A파일이 서비스를 위해 Body를 Load하려고 하였으나 실패함. 파일 초기화 수행 | A파일이 원본서버로 다운로드를 진행하려고 하였으나 원본서버 배제로 실패함 | 이후 A파일은 초기화 시점을 잃어버리고 초기화 상태로 존재함
- 다음 상황에서 Expire/Purge가 성공된 것처럼 나오고 갱신되지 않던 증상 | A파일을 백그라운드로 갱신 시도함 | 원본서버에서 HTTP응답을 받았으나 전송지연이 발생함 | 전송지연으로 연결이 종료되거나 세션이 비정상 종료됐을 때 갱신실패가 제대로 정리되지 않는 상황이 발생함
v1.0.x¶
1.0.17 (2012.11.29)¶
1.0.16 (2012.11.28)¶
1.0.15 (2012.11.22)¶
- 정상적으로 캐싱(200 OK)되어 있는 파일을 갱신하는 과정에서 원본서버로부터 4xx응답을 받았을 때 마치 304 not modified를 받은 것처럼 동작하도록 :ref:`id6`합니다. 이를 통해 서버의 일시적인 장애로부터 컨텐츠를 갱신하는 행위를 방지할 수 있습니다.
- 컨텐츠의 만료시간을 강제로 지정하는 :ref:`expireafter`가 추가되었습니다.
- 원본서버 주소에 포트가 같이 선언되어 있는 경우 포트바이패스가 되지 않던 문제가 수정되었습니다.
- 누적통계가 ON인 상황에서 포트바이패스 통계를 집계하면 비정상 종료되던 문제가 수정되었습니다.
1.0.14 (2012.11.15)¶
- 디렉토리별 통계를 설정했을 때 통계 모니터링 중 비정상종료 될 수 있는 문제가 수정되었습니다.
- 커스텀 TTL 변경이 적용되지않던 증상이 수정되었습니다. 커스텀 TTL은 즉각적으로 반영되지 않고 TTL이 만료되는 시점에 재적용됩니다.
1.0.13 (2012.11.12)¶
- 캐싱된 파일을 최초에 변경확인(If-Modified-Since)으로 접근할 경우 파일이 정상적으로 초기화되지 않던 버그가 수정되었습니다. 이 버그로 인하여 최초 응답시점에 500 Internal Error를 보내거나 TTL이 아주 짧게 설정되어 있는 경우 파일의 유효성이 문제가 될 수 있습니다.
- :ref:`caching-policy-renew`옵션이 ON인 경우 원본서버에서 컨텐츠가 변경되지 않았더라도(304 Not Modified) 최초 접근하는 클라이언트를 무조건 200 OK로 처리하던 증상이 수정되었습니다.
- 정상적으로 캐싱(200 OK)되어 있는 파일을 갱신하는 과정에서 원본서버로부터 5xx응답을 받았을 때 마치 304 not modified를 받은 것처럼 동작하도록 :ref:`id6`합니다. 이를 통해 서버의 임시적인 장애때문에 컨텐츠를 무효화하여 원본 서버 트래픽을 가중시키는 행위를 방지할 수 있습니다.
- SNMP에서 응답 받을 가상호스트의 최대 개수를 :ref:`view`할 수 있습니다.
1.0.12 (2012.11.05)¶
- 요약통계의 수치(원본 트래픽, 세션)가 맞지 않던 증상이 수정되었습니다.
1.0.11 (2012.10.31)¶
- 원본서버가 모두 배제된 상황에서는 Purge/Expire가 동작하지 않습니다.
- 특정 Purge명령이 Expire로 동작하도록 :ref:`caching`할 수 있습니다.
1.0.10 (2012.10.29)¶
- 원본서버가 모두 배제된 상황에서 POST 요청이 클라이언트 세션 수에서 누락되던 증상이 수정되었습니다.
- 원본서버 장애로 인해 Purge된 컨텐츠를 되살리는 과정에서 아직 디스크에 저장되지 않은 컨텐츠를 초기화하던 증상이 수정되었습니다.
1.0.9 (2012.10.22)¶
- 원본서버 HTTP응답의 Content-Disposition헤더를 인지하도록 수정되었습니다.
1.0.8 (2012.10.19)¶
- 원본서버에서 Transfer-Encoding: chunked옵션으로 응답을 줄 때 클라이언트에 Content-Length를 주지 않도록 수정하였습니다.
- 클라이언트의 If-Range헤더를 인지하도록 수정하였습니다.
1.0.7 (2012.10.18)¶
- HTTP요청의 Host필드로 가상호스트를 찾을 때 대소문자 구분하지 않도록 수정되었습니다.
1.0.6 (2012.10.12)¶
- SSLv2 ClientHello를 인식하도록 개선되었습니다.
- 바이패스 중 원본서버가 먼저 연결을 종료하였을 때 오동작하던 증상이 수정되었습니다.
1.0.5 (2012.10.08)¶
- 원본서버 요청 시에 값이 존재하지 않는 QueryString항목이 누락되던 증상이 수정되었습니다.
1.0.4 (2012.10.04)¶
- 원본서버 로그에 QueryString을 기록하지 않던 증상이 수정되었습니다.
1.0.3 (2012.09.28)¶
- 설정파일을 리로드하여도 OriginOptions의 Host설정이 반영되지 않던 증상이 수정되었습니다.
1.0.2 (2012.09.27)¶
- 설정파일을 리로드한 후 Custom TTL설정이 적용되지 않던 증상이 수정되었습니다.
1.0.1 (2012.09.20)¶
- query string 설정이 ON인 경우 Purge/Expire가 과도하게 CPU를 점유하던 문제가 개선되었습니다.
1.0.0 (2012.09.18)¶
- 설정파일을 동적으로 :ref:`reload`할 수 있습니다. 서비스 중단 없이 가상호스트 추가, 삭제, 변경이 가능합니다.
- 하드디스크의 최대사용량을 :ref:`storage`할 수 있습니다. 설정하지 않아도 언제나 디스크가 꽉차지 않도록 관리됩니다.
- 가상호스트의 순서가 변경되더라도 항상 동일한 SNMP의 OID로 통계를 수집할 수 있도록 가상호스트의 OID를 :ref:`vhosts-xml`할 수 있습니다.
- Access 로그를 Apache와 Microsoft IIS형식으로 :ref:`access`할 수 있습니다.
- HTTP응답에 Via헤더 삽입을 :ref:`via`할 수 있습니다.
- 클라이언트의 Accept-Encoding을 무시하도록 :ref:`accept-encoding`할 수 있습니다.
- 콘솔 또는 API를 통해 STON 버전확인이 가능합니다.
- API를 통해 설정파일 열람이 가능합니다.
- 원본서버 로그에 QueryString을 기록합니다.
- SSL을 통한 HTTP Post요청 바이패스가 오동작하던 버그가 수정되었습니다.
- 가상호스트 서비스 포트설정이 <Address>에서 <Listen>으로 :ref:`caching`되었습니다.
- 가상호스트별로 디스크 설정을 별도로 할 수 없습니다. 모든 가상호스트는 <Storage>를 통해 디스크를 공유하도록 :ref:`storage`되었습니다.
- Info로그가 보기 쉬운 형식으로 변경되었습니다.
- fileinfo응답의 시간표현이 “2012.09.03 14:29:50” 같이 읽기쉬운 형태로 변경되었습니다.
v0.9.x¶
0.9.6.7 (2012.08.23)¶
- 바이패스 중 원본과 클라이언트 세션이 동시에 끊어질 때 STON이 비정상 종료되던 버그 수정
- 원본서버가 “Transfer-Encoding: chunked”로 응답을 줄 때 Receive Timeout이 짧게 지정되던 버그 수정
- API응답의 MIME 타입을 application/json에서 text/plain으로 변경
0.9.6.6 (2012.08.01)¶
0.9.6.5 (2012.07.17)¶
- 원본서버를 Active/Standby로 :ref:`env-vhost-standbyorigin`할 수 있습니다.
- Access로그에 클라이언트의 Range필드(cs-range)추가
- HTTP요청이 Invalid Range를 요청하는 경우 동작방식을 변경하였습니다. 기존에는 파일 크기를 벗어난 Range요청은 무조건 416 Requested Range Not Satisfiable으로 처리됐습니다. 이번 버전부터는 끝 오프셋이 파일 크기보다 클 경우 206 Partial Content로 처리됩니다. 시작 오프셋이 파일 크기보다 큰 경우는 기존과 동일하게 처리됩니다.
0.9.6.4 (2012.07.12)¶
- HTTP POST요청 처리시 비정상 종료되던 문제를 수정하였습니다.
- HTTP POST요청의 원본서버 바이패스 여부를 :ref:`bypass-getpost`할 수 있습니다.
- 원본서버 HTTP 응답에 Content-Type헤더가 명시되어 있지 않은 경우 클라이언트에게도 Content-Type헤더를 주지 않습니다. (기존에는 text/html로 설정)
0.9.6.3 (2012.07.11)¶
- HTTPS 요청을 원본서버로 바이패스할 때 잘못된 메모리 참조로 인하여 오동작/비정상 종료되던 문제가 수정되었습니다.
- 투명(Transparent) 모드를 지원합니다. STON과 원본서버 네트워크 구간 사이에 원본서버의 응답을 STON으로 포워딩하는 설정이 필요합니다.
- Expired된 컨텐츠를 서비스하기 전에 반드시 :ref:`caching-policy-renew`하도록 할 수 있습니다.
- 더 이상 URLBypass통계를 별도로 수집하지 않습니다. 원본/클라이언트 트래픽 통계로 통합되었습니다.
- IBM WebLogic에서 클라이언트 Access로그를 남길 수 있도록 WL-Proxy-Client-IP 헤더를 추가할 수 있습니다.
- 원본서버로 보내는 HTTP요청의 X-Forwarded-For헤더의 클라이언트 IP이후를 :ref:`xff-x-forwarded-for`할 수 있습니다.
- 에러 페이지(500 Internal Error)에서 에러이유를 표시합니다.
- 설정에서 문자열의 공백을 제거하지 않던 문제가 수정되었습니다. 모든 문자열의 좌우공백은 제거됩니다.
0.9.6.2 (2012.06.19)¶
- 캐싱되어 있지 않은 파일의 가장 마지막 부분을 Range Request했을 때(Range의 범위가 1024 Bytes미만) 데이터가 전송되지 않던 버그 수정
0.9.6.1 (2012.06.14)¶
CacheClear 기능 추가 - 로 설정된 모든 디스크를 삭제합니다. STON의 모든 서비스는 중단되며 작업이 완료된 뒤 자동으로 재개됩니다.
로그 파일의 OriginOptions의 Host설정 누락이 수정되었습니다.
로그 파일의 Options설정표현이 “TTL”에서 “Options”로 변경되었습니다.
0.9.6 (2012.06.12)¶
SNMP(Simple Network Monitoring Protocol)가 지원됩니다. STON은 항상 실행경로에 MIB(Management Information Base)파일을 생성합니다. STON의 SNMP는 가상호스트별, 실시간, 최근 1~60분까지의 통계를 제공합니다. 최초 실행시 비활성화되어 있으며 server.xml을 편집해 활성화 시킬 수 잇습니다.
<Server><Host><SNMP Port=”161” Status=”Active”><Allow>211.104.97.150</Allow></SNMP></Host></Server>원본서버에서 Content Length없는 응답이 올 경우, Origin로그에 원본서버 에러로 기록하지 않도록 변경되었습니다. 원본서버에서 일방적으로 연결을 종료한 경우, 만약 해당 세션이 Content Length가 없는 HTTP 트랜잭션을 수행 중이었다면 원본에러로 기록되지 않습니다.