Posted
Comments None

꽤 오랜시간동안 delayed_job 을 사용해왔다.
처리 시간이 오래걸리는 작업을 delayed_job 을 통해서 queue 에 넣고 다른 프로세스로 동작을 시키고,
클라이언트에 바로 응답을 줄 수 있으니 나쁘지 않았다.

문제는 delayed_job 이 ruby 의 daemons 로 동작을 하는데
어떤 경우에 delayed_job 데몬이 죽는 경우가 생기는 것이다.
그런 경우가 발생할 때마가 귀찮음에 delayed_job 을 재시작 시키고,
sidekiq이나 resque 같은 녀석으로 대체하려고 생각만 했었다.

최근에도 비슷한 문제를 만나게 되었고 delayed_job 이 죽었을때 다시 실행시키는 감시자(observer) 가 필요하다고 판단이 되었다.
그래서 감시자를 직접 만들기 전에 delayed_job 소스코드를 열어보기 시작했다.ㅋ

몇줄 보기도 전에, daemons 가 핵심인것으로 판단이 되었다.
그리고 daemons 소스코드를 살펴보기 전에 README 파일이 눈에 띄었다.
리눅스를 학습하면서 무수히 들은 얘기가 반드시 README 파일을 읽으라는 것이었다.

역시나..ㅋ
—monitor 옵션에 대한 설명을 발견했고..
delayed_job 이 어떤 원인으로 죽었을때(PID 파일은 있으나 존재하지 않을때) 다시 delayed_job 을 동작시켜주는 감시자를 동작시키는 옵션임을 알게 되었다.

$ script/delayed_job --monitor start

그래서 당분간은 —monitor 옵션과 함께 동작을 시켜보기로 했다.
안정성에 대한 부분은 이론상으론 문제가 없지만 실제 어떤 다른 이슈가 있을지 모르기 때문에..

결론
RTFM

README, man 은 필수!!
문서가 빈약한 경우 source code 까지!!

Author

Posted
Comments None

package main
import (
  "fmt"
  "bytes"
  "encoding/json"
  "net/http"
  "io/ioutil"
)

const API_URL string = "https://android.googleapis.com/gcm/send"
const API_KEY string = "__API__KEY__"

type MessageData struct {
  Score string    `json:"score"`
  Message string  `json:"message"`
}

type Message struct {
  RegistrationIds []string  `json:"registration_ids"`
  Data MessageData          `json:"data"`
  DryRun bool               `json:"dry_run"`
}

func main() {

  md := MessageData{
    Score: "10.23",
    Message: "中国很大",
  }
  m := Message{
    RegistrationIds: []string{
      "__REGISTRATION__ID__",
    },
    Data: md,
    DryRun: true,
  }

  b, err := json.Marshal(m)
  if err != nil {
    panic(err)
  }

  body := bytes.NewReader(b)

  client := &http.Client{}
  req, _ := http.NewRequest("POST", API_URL, body)
  req.Header.Set("Content-Type", "application/json")
  req.Header.Set("Authorization", "key=" + API_KEY)
  res, _ := client.Do(req)

  result, _ := ioutil.ReadAll(res.Body)
  res.Body.Close()
  fmt.Printf("%s\n", result)

}

ruby로 GCM 발송 코드를 만들고 테스트를 한뒤,
golang 으로도 한번 만들어 보았다.
golang 에 관심을 갖게 된건 언어가 병렬처리를 염두하고 설계되었다는 것을 알고 나서부터이다.
CPU 멀티코어의 시대에 언어도 발맞춰야 한다면서..ㅎㅎ

GCM 을 보내는 부분은 크게 2개로 나눌수 있다. 하나는 json 형식의 데이터를 만드는 것이고 다른 하나는 http request 처리이다.

1. JSON marshalling
재밌는 부분(?)은 struct 에서 bytes 형식의 데이터를 만들어 내는 json.Marshal() 함수이다.
json 데이터의 key 이름은 struct 선언부분에서 `json:“score”` 와 같은 형식으로 지정하게 된다.

type MessageData struct {
  Score string    `json:"score"`
  Message string  `json:"message"`
}

자세한 내용은 golang#package_json 을 참고.

2. HTTP Request
POST 방식의 http request 를 처리하는 부분이다.
너무 일반적인 내용이라 특별한 내용은 없다.

  client := &http.Client{}
  req, _ := http.NewRequest("POST", API_URL, body)
  req.Header.Set("Content-Type", "application/json")
  req.Header.Set("Authorization", "key=" + API_KEY)
  res, _ := client.Do(req)

http.Client 의 인스턴스를 할당 받고,
HttpRequest 인스턴스를 만들어 method 지정, url, 전송할 데이터를 포함해준뒤,
http.Client 인스턴스에서 Do() 함수를 호출해주면 된다.

자세한 내용은 golang#package_http 를 참고.

글을 정리하며..
ruby 로 작성한 코드에 비하면 너무 길고, 복잡한게 사실이다.
하지만 CPU 를 효율적으로 활용할 만한 데몬이나 작은 서버를 만드는 경우라면 충분히 고려해볼 만한 언어라고 생각된다.

예전에 golang 을 살펴보다 From zero to Go: launching on the Google homepage in 24 hours 를 보고 큰 감명을 받았다.
늘 실험적이고 연구적인 엔지니어들의 자세와 병렬처리를 위해 설계된 언어가 참 매력적이었다.

Author

Posted
Comments None

Pre-require: rbenv(0.4.0 or higher), ruby-build(20130227 or higher)

$ rbenv install -l
...
2.0.0-p0
...
$ rbenv install 2.0.0-p0

If you got BUILD FAILED message about openssl.

BUILD FAILED

Inspect or clean up the working tree at /var/folders/22/j6zk4q1s6wx2xvx2j8h2kmz80000gn/T/ruby-build.20130313211945.64773
Results logged to /var/folders/22/j6zk4q1s6wx2xvx2j8h2kmz80000gn/T/ruby-build.20130313211945.64773.log

Last 10 log lines:
installing default gems:      /Users/foobargem/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0 (build_info, cache, doc, gems, specifications)
                              bigdecimal 1.2.0
                              io-console 0.4.2
                              json 1.7.7
                              minitest 4.3.2
                              psych 2.0.0
                              rake 0.9.6
                              rdoc 4.0.0
                              test-unit 2.0.0.0
The Ruby openssl extension was not compiled. Missing the OpenSSL lib?

Solution

$ brew install openssl
...
$ CONFIGURE_OPTS='--with-openssl-dir=$(brew --prefix openssl)' rbenv install 2.0.0-p0
...
$

Finally

$ rbenv versions
  system
  1.9.2-p290
  1.9.3-p0
* 2.0.0-p0 (set by /Users/foobargem/.rbenv/version)
$ rbenv global 2.0.0.-p0
$ rbenv rehash
$ ruby --version
ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-darwin12.2.0]
$

Done.

Author

← Older Newer →