서버를 두 대로 늘리면서 앞에 분산기를 뒀다. 그 뒤로 이상한 일이 몇 가지 생겼다.
Table of contents
Open Table of contents
주소의 뜻이 바뀌었다
전에는 도메인 하나가 서버 한 대였는데 이제는 두 대 중 하나가 됐다. 이 차이가 여러 곳에서 드러났다.
file_get_contents('http://shop.example.com/admin/cache/clear');
캐시를 지우는 코드인데 분산기가 아무 대에나 보내니 한 대만 지워진다. 다른 대는 옛 캐시를 계속 쓴다. 코드는 한 줄도 안 바뀌었는데 뜻이 바뀐 것이다.
자기 자신을 부르는 코드를 찾았다
같은 성질을 가진 자리를 전부 찾아야 했다.
$ grep -rn "shop.example.com" --include=*.php application/ | grep -v "base_url"
grep -rn 에서 넷이 나왔다. 캐시 지우기와 설정 다시 읽기와 파일 목록 새로 만들기와 상태 확인인데 넷 다 한 대에서만 일어나면 안 되는 것이었다.
각 대를 IP 로 직접 부르게 고쳤다. 하나가 실패하면 log_message 에 남게 했고 대 목록은 config->item('nodes') 로 뺐다. 코드에 두면 서버를 늘릴 때 잊는다.
file_get_contents 에 $ctx 를 준 것은 기본 default_socket_timeout 이 60초라 한 대가 안 뜨면 전체가 그만큼 늘어지기 때문이다.
$nodes = $this->config->item('nodes');
foreach ($nodes as $ip) {
$r = file_get_contents("http://$ip/admin/cache/clear", false, $ctx);
log_message('info', "cache clear $ip: " . ($r === false ? 'FAIL' : 'OK'));
}
대마다 갖는 것과 공유하는 것
부르는 코드를 고치는 것보다 나은 방법이 있었다. 캐시를 대마다 갖지 않으면 지울 것도 하나다. 파일 캐시를 memcached 로 옮기니 지우는 것도 한 번이 됐다.
전부 옮기지는 못했다. APC 같은 코드 캐시는 그 서버 프로세스 안에 있으니 옮길 수 있는 것이 아니다. 그런 것은 배포할 때 각 대에서 처리하게 했다. 대마다 갖는 것과 공유하는 것을 갈라 정하고 나니 여러 대를 도는 코드가 줄었다.
올린 파일도 같은 문제였다. 관리자가 이미지를 올리면 move_uploaded_file 이 그 대의 디스크에만 쓰고 볼 때 다른 대로 가면 없다. 절반의 확률로 안 보인다. 업로드 폴더를 NFS 로 두 대가 같은 자리를 보게 했다. 그 저장소가 죽으면 둘 다 안 되는 것은 받아들여야 했는데 대신 파일이 한 벌만 있으니 백업도 한 번이면 됐다.
로그도 나뉘어 있어서 조사할 때 둘 다 봐야 했다. 한 자리로 모으는 것은 나중에 만들었고 그 전에는 ssh 로 두 대에 같은 grep 을 돌리는 스크립트를 두고 썼다. 로그 줄에 gethostname 을 넣은 것이 도움이 됐다. 모아 놓고 봐도 어디 것인지 갈린다.
확인 방법도 바뀌었다
고쳤다는 것을 확인하는 방법도 달라졌다. 전에는 주소를 한 번 열어 보면 됐는데 이제는 두 대에 다 반영됐는지 봐야 한다.
$ for h in 10.0.0.10 10.0.0.11; do
echo -n "$h "; curl -s "http://$h/health" | grep -o '"rev":"[^"]*"'
done
각 대의 IP 로 직접 curl 해서 rev 를 비교하는 것이다. 한 번 열어 보고 됐다고 하면 절반만 확인한 것이다. 실제로 한 대만 배포된 채로 며칠 간 적이 있었다. 분산기가 두 대에 나눠 보내니 어떤 사람은 새 판을 보고 어떤 사람은 옛 판을 봤다.
정리
- 주소가 한 대를 가리키다 여러 대를 가리키게 되면 전제가 바뀐다
- 코드가 안 바뀌어도 뜻이 바뀐다
grep -rn으로 자기 도메인을 부르는 코드를 찾는다- 각 대를 IP 로 직접 부르되 목록은
config->item으로 둔다 file_get_contents에$ctx를 줘default_socket_timeout을 줄인다- 부르는 것을 고치기보다
memcached로 옮겨 대마다 안 갖게 한다 APC같은 코드 캐시는 옮길 수 없으니 각 대에서 처리한다- 올린 파일은
NFS로 두 대가 같은 자리를 보게 한다 - 로그 줄에
gethostname을 넣는다 - 각 대의 IP 로
curl해서rev를 비교한다