레일스 최적의 배포 환경이라는 글에서 Apache + ProxyBalancer + Mongrel을 추천한 바 있다. 물론, 우리 팀에서도 저 구성을 사용하고 있다.


그런데, 한가지 문제가 있다. 바로 Mongrel 프로세스들을 재시작하는 경우이다. Production 환경에서는 모든 모듈이 리로드 되지 않기 때문에 재시작이 반드시 필요하다. 그리고 mongrel에 시그널을 보내 전부 리로드 하는 기능이 있다고 나와있지만, 전혀 되지 않는다(잘 안될 거라고 써있기도 하다).


아파치를 가만 두고, mongrel 프로세스들을 모두 재시작하면, ProxyBalancer들은 이 프로세스들을 모두 에러가 난 것으로 간주하여, 한동안 ‘503 Service unavailable’ 에러가 나는 것이다. 문제는 이런 에러 상태에서 정상 상태로 돌아오는데 시간이 걸려, 사용자가 503 에러를 보게 된다는 것이다. 우아한 재시작(graceful restart)의 모습은 절대 아니다.


가장 간단하고 무식한(?) 방법은 mongrel을 재시작하기 전에 아파치를 멈추고, mongrel이 모두 구동된 이후, 아파치를 다시 구동하는 것이다. 웹 서버를 재시작 해야 한다는 점에서 별로 좋은 선택은 아닐 것 같다.


다행히도, balancer_manager라는 아파치 핸들러가 있어서, 이를 이용하면 ProxyBalancer를 좀 더 세밀하게 제어할 수 있다. 현재 ProxyBalancer의 상태를 보는 것은 물론, 작업자 각각의 가중치를 제어하고, 개별적으로 켜고 끌 수도 있다. 자세한 설치 방법은 문서를 참조.

 

그래서 생각한 것이, mongrel_rails의 클러스터 기능을 사용하지 않고, 각각을 하나씩 재시작하는데, 이 때마다 balancer_manager를 통해 직접 해당 작업자를 잠시 껐다가 켜주는 것이다. 그렇게 하면 사용자는 재시작 프로세스가 진행되는 동안에도 에러 메시지나, 끊어짐 없이 서비스를 사용할 수 있다.


사용중인 레이크 스크립트를 아래처럼 수정했다.


  1. def restart
  2.   0.upto(9) do |i|
  3.     stop(i)
  4.     start(i)
  5.   end
  6. end

  7. def stop(i)
  8.   system "wget \"#{BALANCER_MANGER}?lf=1&wr=&rr=&dw=Disable&w=http%3A%2F%2F127.0.0.1%3A400#{i}&b=cluster\" -O /dev/null -q"
  9.   system "mongrel_rails stop -P #{APP_HOME}/shared/log/mongrel.400#{i}.pid -c #{APP_HOME}/current"
  10. end

  11. def start(i)
  12.   system "mongrel_rails start -d -e production -p 400#{i} -a 127.0.0.1 -l #{APP_HOME}/shared/log -P #{APP_HOME}/shared/log/mongrel.400#{i}.pid -c #{APP_HOME}/current"
  13.   system "wget \"#{BALANCER_MANGER}?lf=1&wr=&rr=&dw=Enable&w=http%3A%2F%2F127.0.0.1%3A400#{i}&b=cluster\" -O /dev/null -q"
  14. end


점점 우아한 재시작에 가까워지고 있다. 다음은 DB 스키마가 바뀌는 등, 이전 리비전이 서비스될 수 없을 때도 최대한 우아하게 재시작 할 수 있는 방법을 고민해봐야겠다.

 

4 Responses to “몽그렐을 우아하게 재시작하는 법”

  1. 홍민희 Says:
    기시감이;
  2. kkung Says:
    기시감이; (2)
  3. 글로리 Says:
    카피스트라노 쓰는 사람은 어떻게 적용하나요?
  4. glory Says:
    (myRuby.net) 카피스트라노 쓰는 사람은 어떻게 하나요?adsf

Leave a Reply

Website

Email