예외 알림 플러그인 (Exception Notifier Plugin)

Posted by deepblue Wed, 11 Jul 2007 02:25:49 GMT

레일스 애플리케이션을 배포한 후 Production 환경에서 발생하는 오류를 모니터링할 수 있는 방법이 없을까? 처음에는 레일스 로그 파일을 분석해서 찾아볼 생각을 했으나, 레일스 로그 파일이 엄격한 형식을 따르고 있지 않아서 쉽지 않았다. 그러던 중 찾은 것이 바로 Exception Notifier 플러그인이다.

 

이 플러그인을 설치하면, 예외가 발생되었을 때 미리 설정해둔 메일 주소로 예외가 발생한 상황의 환경과 함께 내용을 전달해준다.  함께 전달되는 정보는 HTTP 요청 정보, 세션, 환경 변수, 예외의 역추적(backtrace)이다. 물론 탬플릿을 바꾸거나 클래스를 확장해서 이 정보를 보강할 수도 있다.

 

이 플러그인은 레일스 서비스를 운영하는데 많은 도움이 된다. 이 플러그인을 사용할 때는 스레드뷰를 지원하는 메일 클라이언트(ex. gmail)를 사용하는 것이 좋겠다. 간혹, 사소한 실수 하나로 수백 수천통의 메일을 날아올 수 있으니 :) 그리고 이 플러그인을 확장해서 예외 정보를 메일 뿐 아니라 데이터베이스나 에러 로그 파일에 따로 남겨놓으면 나중에 따로 분석이 필요할 때 도움이 될 것이다.

 

한가지 주의할 점은 이 플러그인이 ActionController의 rescue_action_in_public을 재정의하고 있기 때문에, 이 메서드를 사용하는 다른 플러그인과 충돌이 생길수도 있다는 점이다. 필자는 플러그인 로드 순서를 조정해서 이 문제를 해결한 적이 있다.


설치 방법

레일스 애플리케이션 ROOT에서 다음 명령으로 플러그인을 설치한다.

  1. script/plugin install exception_notification

 

환경 파일(config/environment.rb)에 메일을 받을 주소와 메일의 prefix를 정해준다. EdgeRails를 사용중이라면 config/initializers/exception_notification.rb 정도의 파일을 만들고 여기에 넣는 것도 좋겠다.

  1. ExceptionNotifier.exception_recipients = %w(admin@myapp.com)
    ExceptionNotifier.email_prefix = “[MY-APP-ERROR] ”

 

그리고 ApplicationController에 다음 줄을 추가해주면 모든 설정이 끝난다.

  1.   class ApplicationController < ActionController::Base
        include ExceptionNotifiable
        …
      end

 

이 글은 스프링노트에서 작성되었습니다.

이 글은 스프링노트에서 작성되었습니다.

스프링노트 UI 개편

Posted by deepblue Tue, 10 Jul 2007 06:35:33 GMT

참조 -  스프링노트 UI가 개편되었습니다.


 스프링노트가 새싹 오픈한 지 약 3달만에 새 옷을 입었다. 이 개편을 위해 5월부터 많은 이야기를 하고 고민을 했다. 그 시간들이 결과로 나타나니 기분이 묘하다. 서비스를 오픈할 때와 그리고 2주단위 릴리즈 노트를 쌓아갈 때와는 또 다른 느낌이다.


attach/1/1001491765.gif


개인적으로는 스프링노트팀이 사용성 개선이라는 하나의 목표를 향해 함께 노력하고 달리는 모습이 너무 즐거웠다. 물론, 몇가지 숙제도 생겼지만 그건 다음에 더 잘하면 되니까. 이 기간에 어설픈 PM 역할을 하면서 느낀바도 많다. 세상에는 어려운 일이 너무 많더라 :)

 

다시 한번 시작이다. 다음은 팀스프링노트다. 많은 사람들이 스프링노트로 행복해졌으면 좋겠다.

이 글은 스프링노트에서 작성되었습니다.

이벤트 기반 몽그렐의 성능 8

Posted by deepblue Wed, 04 Jul 2007 08:08:01 GMT

루비는 자체적인 스레딩 시스템(green thread)을 가지고 있다. 그런데 이 그린 스레드가 빈약한 기능과 성능, 멀티 코어에 대응되지 못하는 등 여러 문제를 가지고 있어서 많은 이슈를 만들고 있다. 그린 스레드를 루비의 장점으로 보는 시각도 있지만, 루비 2.0에서는 그린 스레드가 빠진다, 계속 남는다 등등 아직도 말이 많은 상태다.

 

레일스에서 널리 사용되는 애플리케이션 서버인 몽그렐도 그린 스레드를 이용해 동시 요청을 처리한다. 하지만 지난 RailsConf에서 루비의 Mutual Lock의 성능이 좋지 않고, 되려 스레드간의 문맥 전환에서 상태 정보를 복사하느라 오버헤드가 많다는 주장이 있었다. 그래서 멀티 스레드 몽그렐을 이벤트 기반의 싱글 스레드로 다시 작성하면 성능면에서 얻는 이득이 있다는 것이다.  메모리 사용량, IO 스루풋도 나아진다고 한다.

 

Swifitply에 포함된 evented_mongrel.rb가 바로 몽그렐을 이벤트 기반 싱글 스레드로 바꿔주는 Hotfix이다. 여기에는 EventMachine이라는 네이티브 라이브러리가 사용되었다. 이 fix를  적용하려면 gem으로 EventMachine과 Swiftiply를 모두 설치하고 몽그렐을 시작할 때 환경변수 EVENT를 1로 설정해주기만 하면 된다. Swiftiply가 mongrel_rails를 재정의하는데, 환경변수에 따라 몽그렐이 동작하는 모드를 바꿔준다.

 

  1. gem install eventmachine
  2. gem install swiftiply
  3.  
  4. env EVENT=1 mongrel_rails start -e production -d

 

실제 애플리케이션이 동작하는데 영향을 주는 부분을 바꾸는 것이 없기 때문에 이벤트 기반 몽그렐을 사용한다고 해서 기존 애플리케이션이 동작하지 않는다거나 하는 일은 일어나지 않을 것 같다. 그런데 정말 빠를까? 빠르다면 얼마나 빠를까? 스프링노트에 적용하기 전에 간단한 벤치마크 테스트를 해보았다. 결론부터 이야기하자면, 정말 더 빠르다.

 

벤치마크

테스트를 수행한 장비는 사양은 이렇다.

 

  • CPU: AMD64 2CPU
  • MEMORY 8G
  • 운영체제: RHEL4

 

벤치마크에 사용한 소프트웨는 몽그렐 1.0.1, Swiftiply 0.5.1, EventMachine 0.7.2이고, 레일스의 버전은 EdgeRails 리비전 7161이다. 그리고 테스트를 위해 간단하게 Hello World를 출력하는 애플리케이션을 작성했다.

 

  1. class TestsController < ApplicationController
      def show
        render :text => ‘Hello, Rails’
      end
    end

 

위 애플리케이션을 스레드 모드와 이벤트 모드로 각각 구동하고 동시 요청 수를 1에서 1000까지 늘리면서 테스트를 해보았다.

 

결과

아파치 벤치마크 툴(ab)로 검사한 결과는 다음과 같다.

 

 

결과 중 초당 처리한 요청 수만을 표로 정리하면 아래와 같다.

 

data.png

동시 요청 수에 상관없이 항상 이벤트 기반 몽그렐이 더 나은 성능을 보여줌을 알 수 있다. 특히 주목할만한 점은 동시 요청이 늘어난 즉, 더 가혹한 상황에서 이벤트 기반 몽그렐이 실력을 발휘한다는 사실이다. 기존 몽그렐은 동시 요청이 늘어남에 따라 계속 성능이 떨어지는 모습을 보이지만, 이벤트 기반 몽그렐은 더 나은 성능을 보이기도 하고, 전체적으로 비슷한 수준을 유지함을 알 수 있다.

 

evented_mongrel.png

그래프로 그려보니 그 차이가 더 명확하다.

 

사실 스프링노트에서는 2주째 이벤트 기반 몽그렐을 사용하고 있다.  그간 이벤트 기반 몽그렐때문에 문제가 발생한 적은 한 차례도 없다. 안정적으로 서비스하는데 문제가 없다는 이야기다. 레일스 서비스를 고려한다면, 꼭 이벤트 기반 몽그렐로 바꿔서 성능 테스트를 한번 해보기를 권한다. 공짜로 얻을 수 있는 성능 향상이니까.

 

다음에는 Swiftiply 프록시를 테스해볼 생각이다.  아직 몇 가지 버그가 있는 듯 보여 본격적인 사용은 미루고 있지만, 이는 성능보다는 ‘안정성’에 도움이 될 수 있는 방법이니만큼 꼭 테스트해봐야겠다.

 

이 글은 스프링노트에서 작성되었습니다.

1회 오픈마루 DevDay 후기

Posted by deepblue Tue, 03 Jul 2007 13:07:50 GMT

지난 일요일 오픈마루 DevDay가 열렸다. 너무 썰렁하면 어쩌나 걱정도 했는데, 그것은 기우였고 많은 분들을 만나 이야기를 나눌 수 있는 즐거운 시간이었다.

 

이 날 새로 발표된 것이 있는데, 바로 오픈마루 API 센터myID API이다. 오픈마루 API 센터는 매시업을 개발할 때 가장 큰 집입장벽이라고 할만한 ‘인증’을 획기적으로 개선해 줄 것이라 기대한다. 특히나 OpenID 프로토콜을 확장한 웹기반 인증을 활용하면, 사용자에게 주는 이질감을 최소한으로 하며 매시업을 개발할 수 있는 것으로 많이 활용될 수 있을 것 같다. 팀 스프링노트의 기반 기술로 사용될 myID API도 공개되었는데, 간결하지만 많은 메시지를 담은 좋은 API다. 잘 쓰이면 좋겠다.

 

그리고 스프링노트 API도 조금 나아졌다. 그 전에 다소 혼란스러웠던 부분(입력 방식과 하이픈과 밑줄 문제)을 정리하면서 REST API가 조금 바뀌어 불편을 주기도 했지만 그래도 스프링노트에서 유용해보이는 리소스를 모두 노출시키고 오류 메시지를 강화하고 API 센터를 적용하는 등 개선이 이뤄졌다. 에디터 확장을 포함한 자바스크립트 API도 공식적으로는 이 날 처음 발표되었고, 두번째 세션에서 몇 가지 매시업도 만들어졌다.

 

1322/692889317_aa0624ead9.jpg

<사진> 스프링노트 API를 발표 중. 스프링노트는 크게 두가지 API를 제공하고 있다.

 

 매시업들의 재료가 될 API의 소개가 모두 진행된 다음에는 삼삼오오 모여서 직접 매시업을 만들어보는 시간을 가졌다. 나는 jasonpa님과 함께 루비 튜토리얼을 함께했다. 이 세션에서는 내가 가지고 있던 레일스, REST, OpenAPI 등에 대한 생각들과 스프링노트 API 경험을 공유해드렸고 또 좋은 이야기도 많이 들었다. 그리고 이어서 jasonpa님의 주도로 ActiveResource를 이용해서 데이터베이스 없이 scaffold CRUD 애플리케이션을 만들어보는 실습을 진행했다.

 

시간을 효율적으로 사용하지 못해서, 실제 유용해보이는 매시업을 해보지 못한 것이 무척 아쉽기는 하지만 가능성을 많이 봤다는 점에서 위안을 삼고 싶다. 2회 DevDay에서는 나도 유용한 매시업을 만들어봐야겠다. 이 날 보여드린 스프링노트 클라이언트 라이브러리는 조금만 더 정리해서 곧 공개할 예정이니, 잠시만 기다려주시길.

 

1292/692981263_e208271376.jpg

<사진> 루비 튜토리얼에서 열심히 매시업 개발을 실습 중!

 

처음 하는 DevDay여서 다소 부족한 부분도 있었지만, 전체적으로 매시업 서비스의 가능성을 본 의미있는 시간이었다. 언제가 될지 잘 모르겠지만, 2회 때는 정말 성공적인 매시업 사례가 많이 있어서 이를 축하하고 한발 더 나아갈 수 있으면 좋겠다.

 

 

이 글은 스프링노트에서 작성되었습니다.

몽그렐 클러스터가 필요한 이유 2

Posted by deepblue Thu, 21 Jun 2007 09:07:00 GMT

레일스 애플리케이션을 개발/배포할 때 가장 많이 사용되는 서버가 몽그렐(mongrel)이다. 몽그렐이 나오기 전에는 개발 환경에서는 Webrick(순수 루비 HTTP 서버)을 사용하고, 배포 환경에서는 FastCGI(또는 SCGI)를 즐겨 사용했었는데, 속도와 안정성 측면에서 문제가 많았다. 몽그렐은 구세주 같았다.

 

몽그렐은 레일스 전용이 아닌 일반적인 HTTP 서버 프로그램이다. 하지만 실제 배포 사례들을 보면 꼭 몽그렐을 뒷단(backend)에 두고 앞에는 일반적인 웹서버(아파치나 Nginx같은)를 둔다. 그 이유가 뭘까? 첫 번째 이유는 몽그렐의 정적 파일 처리 능력이 기존의 웹서버 프로그램보다 떨어지기 때문이다. 그래서 라우팅 트릭(rewrite)를 이용해 정적 파일은 기존 웹서버가 처리하도록 하고, 동적 요청(레일스)만을 몽그렐로 전달하게 한다.

 

이보다 근본적인 이유는 몽그렐 클러스터, 즉 몽그렐 프로세스를 여러개 띄우고 이들을 풀(pool)로 활용하기 위해서이다. 여기서 궁금증이 생긴다. 왜 유독 몽그렐만 클러스터가 필수처럼 여겨질까? 몽그렐이 동시 사용자를 처리하지 못하나? 그렇지 않다. 몽그렐은 요청당 한 스레드(루비의 그린쓰레드라는 문제는 있지만)를 사용하며, 완전한 스레드 안전성(Thread Safety)를 보장한다. 그렇다면 왜? 답은 레일스 문화에 있다. 레일스 초창기부터 여러 부분에서 다중 스레드를 고려하지 않아왔기 때문이다. 대부분의 환경에서 단일 스레드로 충분했다고나 할까?

 

ActionController::Base 클래스와 ActiveRecord::Base에 모두 allow_concurrency라는 속성이 정의되어 있고, 이 속성의 기본값은 거짓(false)이다. base.rb를 보면 아래와 같은 코드를 찾을 수 있다.

 

  1. # Action Pack and Active Record are by default thread-safe,
    # but many applications may not be.
  2. # Turned off by default.
    @@allow_concurrency = false
    cattr_accessor :allow_concurrency

 

이 값을 true로 바꾸는 것으로 레일스의 스레드 안전성을 보장받을 수 있을까? 나는 아니라고 생각한다. 이유는 루비 커뮤니티가 스레드 안전성에 익숙하지 않고(애플리케이션에서 사용하는 어떤 코드에서 문제가 일어날지 모른다), 다중 스레드 환경에서 충분한 테스트도 이루어지지 않았기 때문이다. 한마디로 검증되지 않았다는 이유이다. 몽그렐 핸들러를 이용해 작은 프로그램을 처음부터 다중 스레드를 고려해서 만든다면 가능하겠지만, 그렇지 않은 경우 위 옵션을 켜는 것을 추천하지 않는다.

 

이런 이유로 몽그렐의 레일스 핸들러에서 디스패처 전후로 뮤택스(Mutex)를 이용한 동기화를 행하고 있다. 아래는 mongrel-1.0.1/lib/mongrel/rails.rb 코드의 일부이다.

 

  1. module Mongrel::Rails
    1. class RailsHandler < Mongrel::HttpHandler
      1. def process(request, response)
        1. # …
        2. @guard.synchronize {             
          1. @active_request_path = request.params[“PATH_INFO”]
          2. Dispatcher.dispatch(
            1. cgi,
            2. ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS,
            3. response.body)

          3. @activerequestpath = nil     
        3. }
        4. # …
      2. end
    2. end
  2. end

 

이제 몽그렐은 한번에 하나의 요청만을 처리할 수 있다. 따라서 동시 사용자를 처리하기 위해서는 꼭 몽그렐 클러스터가 필요하다. 그래서 개들을 다루는 능력이 레일스 서비스 운영에서 핵심 역량이 되었다.

 

한번에 하나의 요청만을 처리할 수 있기 때문에 레일스 애플리케이션이 요청을 처리하는 전략도 수정되어야 한다. 즉, ‘빠른 응답 시간’을 보장할 필요가 있다. 따라서 오래걸릴 만한 작업이라면 BackgrounDRB 등의 방법을 이용해 백그라운드로 처리하고, 상태만을 반환해야 한다. 얼핏 보기에는 번거러운 작업일 수 있지만, 사용자의 요청에 빨리 응답한다는 면에서 좋을 수도 있겠다.

 

참고 자료

 

이 글은 스프링노트에서 작성되었습니다.

Older posts: 1 2 3 4 ... 22