[Nginx] FastCGI Cache

반응형

이번글에서는 nginx의 fastCGI cahce를 사용해 성능을 향상시키는 방법에 대해 알아보도록 하겠습니다.

1. FastCGI Cache란?

nginx의 simple server side cache 방법입니다.

nginx의 FastCGI Cache 사용해 dynamic language의 response를 저장해 놓으면, server side language process를 최소화시켜 서비스의 성능 향상 및 server의 부하를 감소시킬 수 있습니다.

예를 들어 위와 같이 client가 요청한 작업의 결과물을 php와 같은 server side process가 response할 경우, nginx는 해당 response 값을 client에 전달하기전에 Cache라고 불리는 memory에다 저장해놓을 수 있습니다.

이후 만약 동일한 response값을 client에서 요구할 경우 더이상 php의 작업은 필요하지 않으며, 단순히 nginx의 cache에 저장된 값을 return 합니다.

2. Set FastCGI Cache

이제 FastCGI Cache를 적용해보겠습니다.

nginx에 fastcgi cache를 적용하기위해선 nginx.conf를 수정해야합니다. 먼저 아래와 같은 기본적인 nginx.conf 파일이 있다고 가정하겠습니다.

nginx.conf

worker_processes auto;

events {
    worker_connections  1024;
}


http {
        include mime.types;

        server {
                listen 80;
                root /sites/demo;
                index index.php index.html;

                location / {
                        try_files $uri $uri/ =404;
                }

                location ~\.php$ {
            # Pass php requests to the php-fpm service (fastcgi)
                        include fastcgi.conf;
                        fastcgi_pass unix:/run/php/php7.10fpm.sock;

                }
        }
}

2-1) configure microcache

먼저 fastcgi cache의 configuration을 http에 정의해야합니다. nginx.conf를 vim을 사용해 아래와 같이 수정합니다.

worker_processes auto;

events {
    worker_connections  1024;
}


http {
        include mime.types;
    # Configure microcache (fastcgi)
        fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=ZONE_1:100m inactive=60m;
        fastcgi_cache_key "$scheme$request_method$host$request_uri";

        server {
                listen 80;
                root /sites/demo;
                index index.php index.html;

                location / {
                        try_files $uri $uri/ =404;
                }

                location ~\.php$ {
            # Pass php requests to the php-fpm service (fastcgi)
                        include fastcgi.conf;
                        fastcgi_pass unix:/run/php/php7.10fpm.sock;

                }
        }
}

입력한 내용을 살펴보면 아래와 같습니다.

fastcgi_cache_path : fastcgi cache가 보관될 directory를 명시합니다. 저는 /tmp/nginx_cache에 저장하도록 하겠습니다.

levels=1:2 : cache를 split해서 저장할 depth of directory를 명시합니다. 만약 levels을 따로 명시하지 않을 경우 아래와 같이 모든 cache가 동일한 depth의 level로 저장됩니다.

만약 위와 같이 1:2로 명시한 경우 뒤에서 부터 순서대로 1자리 cache value와

다음 2자리 cache value를 기준으로 directory가 split 되어 계층형으로 저장됩니다.

keys_zone=ZONE_1:100m : cache의 이름을 명시합니다. 사용하고자 하는 이름을 입력합니다. ':' 뒤에는 cache의 size를 정의합니다. 100m(megabyte)은 대부분의 cache를 저장할 수 있는 적절한 크기입니다.

inactive=60m : 특정 cache의 value가 마지막 요청으로부터 최대 얼마의 시간까지 discard 되지 않고 값을 유지할지를 정의합니다. 기본값은 10m(minute)입니다.

fastcgi_cache_key "$scheme$request_method$host$request_uri" : cache의 key 구분자를 정의합니다. "$scheme$request_method$host$request_uri"는 가장 보편적으로 사용되는 key 구분자입니다.

만약 본인의 도메인이 https와 http를 동시에 지원하는 경우에는, $scheme을 생략해 동일한 request에 대한 cache를 동일한 key entry에 저장할 수 있습니다.

만약 $scheme을 생략하지 않는 경우 아래와 같이 https와 http의 request는 서로 다른 cache의 key값을 가지게됩니다.

위와 같은 request uri는 cache에 저장될때 hash 값으로 변환되 저장되게 됩니다. 😎

2-2) enable cache

다음으로 위에서 정의한 fastcgi cache를 사용하기위해 location에 아래와 같이 작성합니다.

worker_processes auto;

events {
    worker_connections  1024;
}


http {
        include mime.types;
    # Configure microcache (fastcgi)
        fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=ZONE_1:100m inactive=60m;
        fastcgi_cache_key "$scheme$request_method$host$request_uri";

    server {
                listen 80;
                root /sites/demo;
                index index.php index.html;

                location / {
                        try_files $uri $uri/ =404;
                }

                location ~\.php$ {
            # Pass php requests to the php-fpm service (fastcgi)
                        include fastcgi.conf;
                        fastcgi_pass unix:/run/php/php7.10fpm.sock;

             # Enable cache
                        fastcgi_cache ZONE_1;
                        fastcgi_cache_valid 200 404 60m;

                }
        }
}

입력한 내용을 살펴보면 아래와 같습니다.

fastcgi_cache MYCACHE : 위에서 정의한 cache를 사용하겠다고 선언합니다.

fastcgi_cache_valid : response 응답코드에 따른 cache의 유효한 시간을 정의합니다. 아래와 같이 작성하면 200 응답코드의 cache값은 60m동안, 404 응답코드의 cache 값은 10m동안 유효합니다.

fastcgi_cache_valid 200 60m
fastcgi_cache_valid 404 10m

3. Test

위와 같이 작성한 후 cache를 적용하기전과 적용후의 성능을 비교해보도록 하겠습니다.

성능을 비교하기위해 apache bench를 사용하도록 하겠습니다.

아래의 명령어를 입력해 apache bench를 다운받습니다.

yum install httpd-tools

정상적으로 다운받아졌다면 아래의 명령어를 입력해 apache bench의 옵션을 살펴볼 수 있습니다.

ab

이제 성능을 시험해보기위해 생성한 index.php에 10x10 request를 요청해보도록 하겠습니다. 😎

index.php

<?php sleep(1); ?>
<h1>Date: <?php echo date("l jS F"); ?></h1>

아래와 같이 명령어를 입력합니다. 100개의 request를 10개의 concurrency로 요청하는 명령어입니다.

ab -n 100 -c 10 http://[request_uri]

3-1) before cache

결과값을 살펴보면 아래와 같이 현재 1 request당 소모되는 시간은 2143.153ms 입니다.

3-2) after cache

이번에는 fastcgi를 적용하고 테스트해보도록 하겠습니다.

아래의 명령어를 입력해 nginx을 reload해 nginx.conf의 변경사항을 반영합니다.

nginx -s reload

이후 동일한 명령어로 테스트를 수행하면 아래와 같이 수행속도가 현저하게 개선된 것을 확인할 수 있습니다. 이는 동일한 request에 대한 결과값은 cache에 저장되어있는 value로 return하기 때문입니다.

이처럼 cache를 사용하면 service의 성능을 비약적으로 향상시킬 수 있습니다. 👏👏👏

3-3) cache header

만약 return한 결과값이 cache에서 return 한 값이라고 명시하고 싶다면, 아래의 header를 nginx.conf에 추가합니다.

# Configure microcache (fastcgi)
fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=ZONE_1:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

add_header X-Cache $upstrea_cache_status;

이후 다시한번 동일한 request를 수행하면 response header에 아래와 같이 cache status가 추가된 것을 확인할 수 있습니다.

3-4) cache exception

fastcgi를 사용하면 아래와 같이 특정조건에서 cache를 bypass 하거나, cache에 response 값을 저장하지 않을 수 있습니다.

worker_processes auto;

events {
    worker_connections  1024;
}


http {
        include mime.types;
    # Configure microcache (fastcgi)
        fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=ZONE_1:100m inactive=60m;
        fastcgi_cache_key "$scheme$request_method$host$request_uri";

    server {
                listen 80;
                root /sites/demo;
                index index.php index.html;

                # cache by default
                set $no_cache 0;

                # check for cache bypass
                if($arg_skipcache=1){
                    set $no_cache 1;
                }

                location / {
                        try_files $uri $uri/ =404;
                }

                location ~\.php$ {
            # Pass php requests to the php-fpm service (fastcgi)
                        include fastcgi.conf;
                        fastcgi_pass unix:/run/php/php7.10fpm.sock;

            # Enable cache
                        fastcgi_cache ZONE_1;
                        fastcgi_cache_valid 200 404 60m;

                        # bypass
                        fastcgi_cache_bypass $no_cache;
            # skip store cache
                    fastcgi_no_cache $no_cache;
                }
        }
}

참고 자료 : https://www.udemy.com/course/nginx-fundamentals/


반응형

'Nginx' 카테고리의 다른 글

[Nginx] HTTPS (SSL)  (0) 2020.08.31
[Nginx] HTTP/2  (0) 2020.08.31
[Nginx] Compressed Response with gzip  (0) 2020.08.31
[Nginx] Header & Expire  (0) 2020.08.31
[Nginx] Adding Dynamic Module  (0) 2020.08.31

댓글

Designed by JB FACTORY