WEB

Nginx FastCGI Cache 설정 및 그누보드5에 적용하기

 

1. Nginx에 내장된 fastcgi_cache 란?

 

 

fastcgi_cache는 기본적으로 php와 같은 동적 컨텐츠를 캐시한다고 보면 됩니다.

 

캐시라는 것을 간단하게 설명드리면

 

1+2=3 이라는 계산 및 결과가 있다고 봅시다.

 

캐시가 없다면 1+2를 서버에서 계산한 후 그 결과값을 보여줍니다.

 

캐시가 있다면 1+2를 서버에서 계산하지 않고 바로 결과값을 보여준다고 보시면 됩니다.

 

그러므로 서버에 부하가 거의 생기지 않게 됩니다.

 

그리고 당연히 속도가 빨라지며, fastcgi_cache의 경우 TTFB(첫 데이터를 받는 시간)이 절반 이하로 내려가더라구요.

 

또한 F5 무한 공격에 대한 방어도 가능하며, 결과적으로 DDOS에도 효과가 있습니다.

 

 

 

2. 캐시폴더 생성

 

 

1] 추천 경로 1

 

기존 Nginx가 깔려있는 폴더에 cache 라는 폴더를 만들어서 그 경로로 넣는게 좋습니다.

 

ex) /etc/nginx/cache 또는 /usr/local/nginx/cache

 

 

2] 추천 경로 2

 

/var/cache/nginx

 

 

해당 경로의 폴더를 미리 생성해둡니다.

 

 

 

1) 캐시폴더 메모리에 마운트하기

 

 

그리고 캐시 폴더를 생성 후 메모리에 마운트하면 메모리를 캐시폴더로 쓸 수 있습니다.

 

원하는 경로에 캐시 폴더를 생성 후

 

nano /etc/fstab

 

위 명령어로 들어가서

 

tmpfs /your/nginx/path/cache tmpfs size=100M,mode=0755 0 0

 

위와 같은 형식으로 캐시폴더 경로를 지정하면 됩니다. size=100M 는 메모리가 많다면 더 크게 해줘도 상관없습니다.

 

컨트롤 + O, 엔터, 컨트롤 + X 로 저장 후 

 

mount -a

 

위 명령어로 마운트시킬 수 있습니다.

 

마운트 해제하려면 

 

umount /your/nginx/path/cache

 

위 명령어를 넣으면 마운트가 해제됩니다.

 

 

2) 캐시폴더 권한 주기

 

Nginx에 캐시폴더 권한을 줍니다.

 

chown www-data:www-data /your/nginx/path/cache

 

 

 

3. Nginx의 설정파일 nginx.conf 설정하기

 

# FastCGI cache settings
fastcgi_cache_path /your/nginx/path/cache levels=1:2 keys_zone=fastcgicache:30m inactive=30m max_size=100m;
fastcgi_cache_key "$scheme$request_method$host$request_uri$mobile_request";
fastcgi_cache_use_stale error timeout invalid_header updating http_500 http_503;
fastcgi_cache_valid 200 301 302 30m;
fastcgi_cache_valid 404 1m; 
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
fastcgi_keep_conn on;
 
 
map $http_user_agent $mobile_request
{
 default                  fullversion;
 
 "~*phone"   mobileversion;
 "~*samsung"    mobileversion;
 "~*lgtel"   mobileversion;
 "~*mobile"  mobileversion;
 "~*[^A]skt"   mobileversion;
 "~*nokia"   mobileversion;
 "~*blackberry"   mobileversion;
 "~*android"   mobileversion;
 "~*sony"   mobileversion;
 "~*iphone"   mobileversion;
}
 
map $request_method $cache_off {
default 0;
POST 1;
}
 
map $request_uri $cache_off {
default 0;
/bbs/login.php 1;
/bbs/logout.php 1;
/bbs/login_check.php 1;
/bbs/register.php 1;
/bbs/password_lost.php 1;
}
 
map $http_cookie $cache_off {
default 0;
~bG9naW4%3D 1; # gnuboard custom autologin-cookie
}
 
map $http_cookie $cache_off {
default 0;
~bG9naW5fbm9ybWFs 1; # gnuboard custom normal-cookie
}

 

 

위 설정에서 하나씩 뜯어보겠습니다.

 

fastcgi_cache_path /your/nginx/path/cache levels=1:2 keys_zone=fastcgicache:30m inactive=30m max_size=100m;

 

위 설정에서 보면 /your/nginx/path/cache 캐시폴더의 위치를 지정해주고 있습니다.

 

그리고 keys_zone=fastcgicache:30m 는 캐시의 이름을 fastcgicache 라고 지정하는 것이고 30m은

 

메모리를 30m 쓰겠다는 말입니다.

 

inactive=30m 는 30분 동안 접근되지 않은 캐시파일은 삭제된다는 말입니다.

 

max_size=100m 는 옵션입니다. 캐시파일의 총용량을 100MB라고 지정한다는 말이고, 100MB가 넘어가면

 

가장 먼저 생성된 캐시파일부터 삭제됩니다.

 

위에 100MB 용량을 메모리에 마운트 했다면 max_size 옵션을 필요없습니다. 어짜피 100MB 넘어가면 삭제되니깐요.

 

그리고 중요하게 봐야 될 것이 fastcgi_cache_valid 200 301 302 30m; 입니다.

 

응답코드가 200 301 302 로 오는 것을 캐시하고 그 캐시파일의 유효기간을 30분을 잡는 것입니다.

 

즉 한번 캐시되면 30분 동안 글을 쓰거나 댓글을 써도 업데이트가 되지 않습니다.

 

제 홈페이지처럼 블로그 역할을 하는 경우 1h 와 같이 1시간동안 캐시해도 상관없지만

 

커뮤니티 사이트처럼 빠르게 글이 생성되거나 댓글이 많을 경우는 1m (1분) 또는 30s (30초)도 좋은 옵션인 것 같습니다.

 

이건 사이트를 운영하면서 설정값을 수정해주시는게 좋을 것 같습니다. 참고로 저는 1h로 1시간 동안 유효하게 해뒀습니다.

 

 

map $http_user_agent $mobile_request

{

 default                  fullversion;

 

 "~*phone"   mobileversion;

 "~*samsung"    mobileversion;

 "~*lgtel"   mobileversion;

 "~*mobile"  mobileversion;

 "~*[^A]skt"   mobileversion;

 "~*nokia"   mobileversion;

 "~*blackberry"   mobileversion;

 "~*android"   mobileversion;

 "~*sony"   mobileversion;

 "~*iphone"   mobileversion;

}

 

윗 부분은 기본은 fullversion이라고 지정하고, 나머지 지정된 것들은 mobileversion이라고 지정하는 것입니다.

 

이 부분이 들어가는 이유는, 그누보드의 경우 모바일과 PC 버전의 경로는 같지만 실제 보는 화면이 다르기 때문입니다.

 

이 부분이 없다면 모바일 화면으로 먼저 캐시되었다면 해당 경로로 PC에서 보면 모바일 화면으로 보입니다. 

 

그래서 꼭 필요한 부분입니다.

 

 

map $request_uri $cache_off {

default 0;

/bbs/login.php 1;

/bbs/logout.php 1;

/bbs/login_check.php 1;

/bbs/register.php 1;

/bbs/password_lost.php 1;

}

 

윗 부분은 해당경로는 캐시하지 않겠다는 말입니다.

 

로그아웃 유저가 접근할 수 있기 때문에 넣어줬습니다.

 

 

map $request_method $cache_off {

default 0;

POST 1;

}

 

윗 부분은 POST의 경우 캐시를 하지 않는다라는 것입니다.

 

보통 글을 쓸 경우 그렇죠. 하지만 로그인 상태의 경우는 어짜피 캐시가 되지 않으니 상관없을 것 같긴하지만... 

 

보통 지정을 많이 해두더라구요.

 

 

map $http_cookie $cache_off {

default 0;

~bG9naW4%3D 1; # gnuboard custom autologin-cookie

}

 

map $http_cookie $cache_off {

default 0;

~bG9naW5fbm9ybWFs 1; # gnuboard custom normal-cookie

}

 

마지막으로 윗 부분은 bG9naW4%3D 와 bG9naW5fbm9ybWFs 라는 쿠키가 있다면 캐시를 하지 않는다 라는 말입니다.

 

뒤에 gnuboard custom cookie를 붙인 이유는 제가 임의로 쿠키를 지정했기 때문입니다.

 

원래는 워드프레스처럼 wp-login 이라는 내용을 넣고 싶었는데... 실력부족으로 넣지 못했습니다.

 

이건 아래에 그누보드 쿠키 생성 부분에 좀더 글을 넣어보겠습니다.

 

 

4. sites-available의 서버 설정 수정하기

 

이제 Nginx의 서버 설정 파일을 수정할 차례입니다.

 

server { 안에 있는

 

location ~ \.php$ {  php 로케이션 부분에 넣는 것입니다.

 

fastcgi_cache fastcgicache;
add_header X-Cache $upstream_cache_status;
fastcgi_cache_bypass $cache_off; 
fastcgi_no_cache $cache_off;

 

fastcgi_cache fastcgicache; 는 fastcgicache 라는 캐시이름을 캐시로 이용하겠다는 말입니다.

 

add_header X-Cache $upstream_cache_status; 이 부분은 캐시에 X-Cache라는 헤더를 붙여서 실제 

 

캐시가 HIT(적중)했는지 확인할 수 있게 해줍니다. (이건 옵션)

 

fastcgi_cache_bypass $cache_off; 

fastcgi_no_cache $cache_off;

 

윗 부분은 cache_off 라고 지정된 것들은 캐시를 하지 않는다 라는 말입니다.

 

이제 Nginx의 설정은 끝났습니다. 설명은 엄청 길었지만 실제 적용하는 시간은 1분이 채 걸리지 않습니다.

 

참 쉽죠?

 

 

5. 그누보드에 로그인 로그아웃 쿠키 생성 및 제거 코드 넣기

 

로그인 쿠키를 넣는 이유는 유저가 로그인 했을 경우 캐시를 하지 않기 위함입니다.

 

이것을 지정하지 않으면 로그인하지 않은 유저가 로그인한 유저의 화면을 볼 수 있기 때문입니다.

 

 

1) /bbs/login_check.php 에는 대략 53번째 줄에 있는

 

// 3.26
// 아이디 쿠키에 한달간 저장
if ($auto_login) {
// 3.27
// 자동로그인 ---------------------------
// 쿠키 한달간 저장
$key = md5($_SERVER['SERVER_ADDR'] . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] . $mb['mb_password']);
set_cookie('ck_mb_id', $mb['mb_id'], 86400 * 31);
set_cookie('ck_auto', $key, 86400 * 31);
// 자동로그인 end ---------------------------
} else {
set_cookie('ck_mb_id', '', 0);
set_cookie('ck_auto', '', 0);
}

 

위 코드를

 

// 3.26
// 아이디 쿠키에 한달간 저장
if ($auto_login) {
// 3.27
// 자동로그인 ---------------------------
// 쿠키 한달간 저장
$key = md5($_SERVER['SERVER_ADDR'] . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] . $mb['mb_password']);
set_cookie('ck_mb_id', $mb['mb_id'], 86400 * 31);
set_cookie('ck_auto', $key, 86400 * 31);
// 자동로그인 end ---------------------------
// 자동로그인 FastCGI_Cache 용 쿠키 한달간 저장 시작 -----
set_cookie("login_check", "login", 86400 * 31);
// 자동로그인 FastCGI_Cache 용 쿠키 한달간 저장 end -----
} else {
set_cookie('ck_mb_id', '', 0);
set_cookie('ck_auto', '', 0);
// 자동로그인 FastCGI_Cache 용 쿠키 제거 시작 -----
set_cookie("login_check", '', 0);
// 자동로그인 FastCGI_Cache 용 쿠키 제거 end -----
// 일반로그인 FastCGI_Cache 용 쿠키 3시간 저장 시작 -----
set_cookie("login_check_normal", "login_normal", 10800);
// 일반로그인 FastCGI_Cache 용 쿠키 3시간 저장 end -----
}

 

위 코드로 완전 수정합니다. 

 

 

2) /bbs/logout.php 

 

// 자동로그인 해제 --------------------------------
set_cookie('ck_mb_id', '', 0);
set_cookie('ck_auto', '', 0);
// 자동로그인 해제 end --------------------------------

 

위 코드 바로 밑에

 

// 자동로그인 FastCGI_Cache 용 쿠키 제거 시작 -----
set_cookie("login_check", '', 0);
// 자동로그인 FastCGI_Cache 용 쿠키 제거 end -----
// 일반로그인 FastCGI_Cache 용 쿠키 제거 시작 -----
set_cookie("login_check_normal", '', 0);
// 일반로그인 FastCGI_Cache 용 쿠키 제거 end -----

 

위 코드들 추가

 

 

아까 윗부분에 말씀드린 bG9naW4%3D 쿠키 기억나시나요?

 

이게 바로 login 이 변환된 값입니다.

 

워드프레스의 경우 일반 문자인 wp-login 이라는게 들어가는데 저는 아무리해도 일반 문자가 안들어가지더라구요 ㅠㅠ

 

이건 혹시 아시는 분은 도움 바랍니다. (실제 기능상은 전혀 문제없습니다.)

 

 

3) /common.php

 

대략 386번째 줄 

 

// 자동로그인 end-----
}

 

위 코드 바로 밑에

 

//FastCGI Cache 설정 중에 필요한 내용 시작 ---------------
if ($_SESSION['ss_mb_id']) { // 로그인중이라면 노말 쿠키 3시간 생성
set_cookie("login_check_normal", "login_normal", 10800);
} else { // 로그아웃중이라면 노말쿠키 삭제
set_cookie("login_check_normal", '', 0);
}
//FastCGI Cache 설정 중에 필요한 내용 끝 -----------------

 

위 코드 추가하면 됩니다.

 

이러면 로그인 중에는 항상 3시간짜리 쿠키가 생성이 되고, 로그인 세션이 끝난 후 로그아웃이 되면 쿠키가 삭제됩니다.

 

 

 

4) 소셜로그인

 

 

혹시나 아미나 소셜로그인 플러그인이나 기타 소셜로그인을 사용하고 있다면

 

소셜로그인 check 부분에도 쿠키 삽입 부분이 들어가야 합니다.

 

http://amina.co.kr/bbs/board.php?bo_table=skin_amina&wr_id=150

 

위 링크에 있는 아미나 소셜로그인 플러그인을 예를 들면

 

/plugin/login-oauth/oauth_check.php

 

위 파일에서

 

// 회원정보
$mb = get_member($mb_id);

 

위 내용 바로 밑에

 

 

// 일반로그인 쿠키 설정 시작------------------
// 쿠키 3시간 저장
set_cookie("login_check_normal", "login_normal", 10800); 
// 일반로그인 쿠키 설정 end ------------------

 

위 내용을 넣어주면 됩니다.

 

 

6. Nginx Reload 시켜주기

 

service nginx reload

 

위 명령어로 리로드 시켜주고 사이트에 들어가보면 캐시된 사이트를 만나실 수 있습니다.

 

첫 접속은 캐시를 해야되기 때문에 평소가 같은 속도이지만, 다시 접속하거나 F5를 누르면 훨씬 빠르게 느껴시질 겁니다.

 

실제 캐시파일이 생성되는지 확인해보시려면 /your/nginx/path/cache 폴더에 보면 특이한 이름의 폴더가 몇개 생성된 것을 볼 수 있습니다.

 

 

 

 

7. 속도 체감을 눈으로 확인하는 방법

 

크롬 기준 TTFB 보는 방법을 소개해드리겠습니다.

 

 

1. F12를 누른 후 Network 항목을 클릭 

 

2. F5를 눌러 새로고침 

 

3. 파일이 주르륵 나오는데 해당 도메인 파일을 클릭하지 말고 오른쪽에 그래프? 같은 것이 있는데 (보라색 네모박스) 

 

그 그래프에 마우스를 갖다대고 있으면 TTFB가 나옵니다. 

 

 

TTFB는 Time To First Byte 라고 서버에 요청 후 첫번째 데이터를 받는 시간이라고 보시면 됩니다. 

 

네이버나 SIR 같은 좋은 서버의 경우 10 ~ 20ms 정도로 최상급의 성능을 보여준다고 보시면 됩니다. 

 

 

제 서버는 집에서 직접 돌리고 있는 홈서버에다가 저전력 CPU라 성능이 낮지만 fastcgi_cache로 HIT 하면 TTFB 가 10~30ms로 

 

최상급의 서버와 비슷한 성능을 보여줍니다. 

 

 

그게 바로 제가 캐시를 적용하고 싶은 이유입니다.

 

 

8. 실제 캐시된 파일이 제대로 작동하는지 보는 방법

 

크롬 기준 x-cache HIT 보는 방법을 소개해드리겠습니다.

 

 

F12를 눌러서 Network를 누른 후 F5를 누르면 파일이 주르륵 뜹니다. 

 

제일 위에 있는 도메인 파일을 클릭해서 Header 정보를 보면 x-cache 부분이 있고 

 

HIT이면 캐시된 파일이고, EXPIRED면 새로 캐시 파일을 생성한 것입니다. 

 

그래서 FFTB를 보면 기존의 절반 이하인 것을 확인할 수 있습니다.

 

 

9. 알려진 버그

 

동시에 로그인한 유저가 있다면

 

먼저 로그인한 계정으로 댓글이 달릴 수 있습니다.

 

지금 해보니깐 안그런데... 어떤 상황에서 이런 일이 벌어지는지 모르겠네요. ㅠㅠ

 

https://www.wsgvet.com/home/511 

 

버그는 위 링크에 정리해뒀습니다.

, , , , , , , , , , ,

2 Comments
마가 2018.07.31 07:00  
지금은 그누보드에 fast cgi 적용해도 문제없나요?

이대로 적용해도 될까요?
우성군 2018.08.05 14:08  
[@마가] 이대로 적용하면 안됩니다. 저도 쓰다가 바로 롤백했습니다.