NGINX Plus R15 에는 HTTP/2 서버 푸시에 대한 지원도 포함되어 있습니다.
2018년 2월 20일 에 출시된 NGINX 1.13.9에 HTTP/2 서버 푸시 지원이 포함되었다는 소식을 전해드리게 되어 기쁩니다. NGINX Plus 사용자를 위해, 2018년 4월에 출시될 NGINX Plus R15 릴리스에 HTTP/2 서버 푸시 지원이 포함될 예정입니다.
HTTP/2 사양에 정의된 서버 푸시를 사용하면 서버가 클라이언트가 곧 해당 리소스를 요청할 수도 있다는 것을 예상하고 원격 클라이언트에 리소스를 미리 푸시할 수 있습니다. 이렇게 하면 페이지 로드 작업에서 RTT(왕복 시간, 즉 요청과 응답에 필요한 시간) 수를 1RTT 이상 줄일 수 있고, 이를 통해 사용자에게 더 빠른 응답을 제공할 수 있습니다.
서버 푸시는 클라이언트에게 웹 페이지를 렌더링하는 데 필요한 스타일 시트, 이미지 및 기타 리소스를 제공하는 데 사용될 수 있습니다. 필요한 리소스만 푸시하도록 주의해야 합니다. 클라이언트가 이미 캐시했을 가능성이 있는 리소스는 푸시하지 마세요.
이 블로그 게시물에서는 다음 내용을 설명합니다.
nghttp
사용)링크
헤더를 사용하여 자동으로 콘텐츠 푸시페이지 로드와 함께 리소스를 푸시하려면 다음과 같이 http2_push
지시문을 사용합니다.
server { # 서버에 대해 HTTP/2가 활성화되어 있는지 확인하세요 listen 443 ssl http2 ; ssl_certificate ssl/certificate.pem; ssl_certificate_key ssl/key.pem; root /var/www/html; # 클라이언트가 demo.html을 요청할 때마다 # /style.css, /image1.jpg 및 /image2.jpg도 푸시합니다 location = /demo.html { http2_push /style.css; http2_push /image1.jpg; http2_push /image2.jpg; } }
다음 두 가지 방법 중 하나를 사용하여 서버 푸시가 적용되었는지 쉽게 확인할 수 있습니다.
nghttp
와 같은 명령줄 HTTP/2 클라이언트다음은 Google Chrome을 예로 들어, 웹 브라우저의 개발자 도구를 사용하여 서버 푸시가 적용되는지 확인하는 방법입니다. 그림에서 Chrome 개발자 도구의 네트워크 탭에 있는 개시자 열은 /demo.html 에 대한 요청의 일부로 여러 리소스가 클라이언트에 푸시되었음을 나타냅니다.
nghttp
)로 확인웹 브라우저 도구 외에도 nghttp2.org 프로젝트의 nghttp
명령줄 클라이언트를 사용하여 서버 푸시가 제대로 작동하는지 확인할 수 있습니다. GitHub 에서 nghttp
명령줄 클라이언트를 다운로드하거나, 가능한 경우 적절한 운영 체제 패키지를 설치할 수 있습니다. Ubuntu의 경우 nghttp2-client
패키지를 사용하세요.
출력에서 별표(*)는 서버에서 푸시된 리소스를 표시합니다.
$ nghttp -ans https://example.com/demo.html id responseEnd 요청 시작 프로세스 코드 크기 요청 경로 13 +84.25ms +136us 84.11ms 200 492 /demo.html 2 +84.33ms * +84.09ms 246us 200 266 /style.css 4 +261.94ms * +84.12ms 177.83ms 200 40K /image2.jpg 6 +685.95ms * +84.12ms 601.82ms 200 173K /image1.jpg
많은 경우, NGINX 설정 파일에 푸시하려는 리소스를 나열하는 것은 불편하거나 심지어 불가능합니다. 이러한 이유로 NGINX는 Link
사전 로드 헤더를 가로채서 이 헤더에서 식별된 리소스를 푸시하는 규칙도 지원합니다. 사전 로드를 활성화하려면 구성에 http2_push_preload
지시문을 포함하세요.
server { # 서버에 대해 HTTP/2가 활성화되어 있는지 확인합니다. listen 443 ssl http2 ; ssl_certificate ssl/certificate.pem; ssl_certificate_key ssl/key.pem; root /var/www/html; # 링크 헤더를 가로채서 요청된 푸시를 시작합니다. location = /myapp { proxy_pass http://upstream; http2_push_preload on; } }
예를 들어, NGINX가 프록시(HTTP, FastCGI 또는 기타 트래픽 유형)로 작동하는 경우 업스트림 서버는 다음과 같은 Link
헤더를 응답에 추가할 수 있습니다.
링크: </style.css>; as=style; rel=preload
NGINX는 이 헤더를 가로채서 /style.css 의 서버 푸시를 시작합니다. Link
헤더의 경로는 절대 경로여야 합니다. ./style.css 와 같은 상대 경로는 지원되지 않습니다. 경로에는 선택적으로 쿼리 문자열이 포함될 수 있습니다.
여러 객체를 푸시하려면 여러 Link
헤더를 제공하거나 더 나은 방법으로 모든 객체를 쉼표로 구분된 목록에 포함할 수 있습니다.
링크: </style.css>; as=style; rel=preload, </favicon.ico>; as=image; rel=preload
NGINX가 미리 로드된 리소스를 푸시하지 않도록 하려면 헤더에 nopush
매개변수를 추가하세요.
# 리소스가 푸시되지 않았습니다. 링크: </nginx.png>; as=image; rel=preload; nopush
http2_push_preload가
활성화된 경우 NGINX 구성에서 응답 헤더를 설정하여 사전 로드 서버 푸시를 시작할 수도 있습니다.
add_header 링크 "</style.css>; as=style; rel=preload";
HTTP/2 사양은 리소스를 푸시할지 여부를 결정하는 문제를 다루지 않습니다. 분명히, 리소스가 필요할 가능성이 높고 이미 캐시되었을 가능성이 낮은 경우에만 클라이언트에 리소스를 푸시하는 것이 가장 좋습니다.
한 가지 가능한 접근 방식은 사이트를 처음 방문한 클라이언트에게만 리소스를 제공하는 것입니다. 예를 들어 세션 쿠키가 있는지 테스트하고 Link
헤더를 조건부로 설정하면 세션 쿠키가 없는 경우에만 리소스가 미리 로드됩니다.
클라이언트가 정상 작동하고 후속 요청에 쿠키를 포함한다고 가정하면 다음 구성을 사용하면 NGINX는 브라우저 세션당 한 번만 리소스를 클라이언트에 푸시합니다.
서버 {
청취 443 ssl http2 기본 서버;
ssl_certificate ssl/certificate.pem;
ssl_certificate_key ssl/key.pem;
루트 /var/www/html;
http2_push_preload 켜짐;
위치 = /demo.html {
add_header 쿠키 설정 "세션=1";
add_header 링크 $resources;
}
}
맵 $http_cookie $resources {
"~*세션=1" "";
기본 "</style.css>; as=style; rel=사전 로드, </image1.jpg>; as=image; rel=사전 로드, </image2.jpg>; as=image; rel=사전 로드";
}
서버 푸시의 효과를 측정하기 위해 /style.css 라는 별도의 스타일 시트를 참조하는 간단한 테스트 페이지 /demo.html을 만들었습니다. 스타일시트는 또한 두 개의 이미지를 참조합니다. 우리는 세 가지 다른 구성을 사용하여 페이지 로드 시간을 테스트했습니다.
GET
(최적화 없음) – 브라우저는 필요한 리소스를 발견했을 때 리소스를 로드했습니다.링크
헤더)는 브라우저에 종속성을 로드하도록 알리기 위해 첫 번째 응답에 포함되었습니다.우리는 HTTP, HTTPS 또는 HTTP/2를 사용하여 각 구성에 대해 여러 번의 테스트를 수행했습니다. 처음 두 구성은 세 가지 프로토콜 모두에 적용되고 서버 푸시는 HTTP/2에만 적용됩니다.
동작은 Chrome 개발자 도구를 사용하여 측정되었습니다. 각 구성의 가장 흔한 동작을 평가하여 평균화했으며, 각 방법의 기계적 효과를 설명하기 위해 시간을 링크의 RTT( ping을
사용하여 측정)와 상관시켰습니다.
GET
작업은 약 1 RTT로 완료됩니다.GET
요청에 대한 0.5 RTT가 발생했습니다.keepalive_timeout
과 http2_idle_timeout은
keepalive 연결을 빠르게 닫는 데 사용되었습니다.이 테스트는 사전 로드 힌트와 서버 푸시의 메커니즘을 강조하기 위해 의도적으로 단순하게 만들어졌습니다. 서버 푸시는 간단한 상황에서 사전 로드 힌트보다 1‑RTT 개선을 제공하고, 최적화되지 않은 순차적 GET
요청 및 종속 리소스 검색과 비교하면 더 큰 개선을 제공합니다.
보다 현실적인 사용 사례에는 훨씬 더 많은 변수가 있습니다. 여러 개의 종속 리소스, 여러 소스, 이미 캐시되거나 즉시 필요하지 않은 리소스를 푸시하여 대역폭을 낭비할 가능성도 있습니다. 브라우저 불일치도 성능에 영향을 미칩니다. 이 간단한 테스트를 통해 여러분은 분명 많은 것을 얻을 수 있을 것입니다.
예를 들어, Chrome 팀은 서버 푸시를 배포하는 시기에 대한 자세한 권장 사항을 게시했으며, 더 복잡한 사이트에서 최적화 없음, 사전 로드 힌트, HTTP/2를 통한 서버 푸시의 효과를 비교하기 위해 측정을 수행했습니다. HTTP/2 푸시에 대한 경험 규칙 보고서는 프로덕션에 HTTP/2 서버 푸시를 배포하는 것을 고려하는 사람이라면 꼭 읽어볼 만합니다.
실용적인 결론은 미리 필요한 리소스를 식별할 수 있다면 업스트림 서버에서 사전 로드 힌트를 보내는 데 실질적인 이점이 있다는 것입니다. 이러한 리소스를 활용하는 데 따른 추가적 이점은 적지만 측정할 수 있지만, 필요한 리소스에 대한 대역폭 낭비와 지연이 발생할 가능성이 있습니다. 모든 서버 푸시 구성을 신중하게 테스트하고 모니터링해야 합니다.
아래 정보는 Jake Archibald의 매우 자세한 HTTP/2 푸시는 생각보다 힘들다는 블로그 게시물에서 조사한 내용을 일부 기반으로 합니다.
HTTP/2 서버 푸시는 일반적으로 클라이언트가 리소스를 요청할 때 종속 리소스를 사전에 전송하는 데 사용됩니다. 예를 들어, 클라이언트가 웹 페이지를 요청하면 서버는 종속 스타일 시트, 글꼴, 이미지를 클라이언트에 푸시할 수 있습니다.
클라이언트가 HTTP/2 연결을 만들면 서버는 해당 연결을 통해 하나 이상의 서버 푸시 응답을 시작할 수 있습니다. 이러한 푸시는 클라이언트가 명시적으로 요청하지 않은 리소스를 전송합니다.
클라이언트는 푸시를 거부( RST_STREAM
프레임 전송)하거나 수락할 수 있습니다. 클라이언트는 푸시된 콘텐츠를 HTTP/2 연결과 연결된 로컬 "푸시 캐시"에 저장합니다.
나중에 클라이언트가 설정된 HTTP/2 연결을 사용하여 리소스에 대한 요청을 하면 해당 요청에 대한 완료되거나 전송 중인 응답이 있는지 연결의 푸시 캐시를 확인합니다. 리소스에 대한 새로운 HTTP/2 요청을 하는 것보다 캐시된 리소스를 우선적으로 사용합니다.
푸시된 모든 리소스는 (a) 사용되거나 (b) HTTP/2 연결이 닫힐 때까지 연결당 푸시 캐시에 남아 있습니다.
이는 여러 가지 의미를 갖습니다.
Jake Archibald의 HTTP/2 푸시는 생각보다 힘들다는 블로그 게시물에서 훨씬 더 자세한 문제 목록을 검토할 수 있습니다.
HTTP/2 서버 푸시는 흥미로운 기능입니다. HTTP/2 서버 푸시 구성을 철저히 테스트하고, 더 예측 가능하고 캐시를 인식하는 동작이 발생하는 경우 사전 로드 힌트로 대체할 준비를 하세요.
"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."