読者です 読者をやめる 読者になる 読者になる

ぱいぱいにっき

Pythonが好きすぎるけれど、今からPerlを好きになりますにっき

Kageをちょっとだけ使ってみた

Perl テスト Ruby

はい、どうも、マコピーです。最近中学生と言われて気にしておりましたが、本日id:hisaichi5518に「小学生みたい」って言われました。記録更新です。

Kageって

Perl界のロックスターであり最近はポッドキャストなどで話題のmiyagawaさんが書かれたよくわからないモジュールなんですが、これってRubyなんですよね。しかもよく見たらcookpad/kageだし、そういえばmiyagawaさん、cookpadさんにいるんでしたね。

出た時になんか気になってドキュメント見たんですが、"shadow requests"とか書いてあって????ってなってよく分からずに閉じてしまっていたのでした。

その後、こんなツイートをいつぞやにしたんですが、

それに@さんからリプライが飛んできて、

こんな感じでやっとKageの使い方というか正体がわかったんですね。なるほどです。

いろんな使い方があると思うんですが、僕は継続的デプロイの文脈上で使いたくて、僕のやってるソーシャルゲームなんかは、結構な頻度でデプロイする場面っていうのがあるんですね。だからデプロイを安全に、素早くやりたい。安全にというところで自動化という話が出るんですが、まあここはCinnamonなりCapistranoなり、Archerなりでがんばってもらうとして、でもそれでほんとうに安全にいけるの? 自動デプロイだとすぐにコケたりしてヤバくなるとかそんなこと無い? っていう不安があるわけで。
たいていは自動デプロイ掛かる前にテスト通してコケたらそこでデプロイ中止するはずなので大丈夫でしょうが、負荷かけると落ちるとか、本番の負荷とかを掛けないと出てこない問題もあるだろうと。
そこでKageでリクエストをコピーしてデプロイ候補のアプリに投げてレスポンスを見て比較して〜みたいなのが出来たらサイコーですね! っていうことです。

Kageの使い方

使い方といってもただドキュメントを写経してさらに1時間ぐらいしか使っていないわけですが、

例えばこういうRackのサーバがあったとして

require 'rack'

class Sample
  def call(env)
    [200,{},["Hello, ruby"]]
  end
end

run Sample.new

こいつをrackupするわけですけれど、さらにもう一個、plackのサーバを用意する

plackup -e 'sub { [200, [], ["Hello, perl"]] }'

ワンライナー、ウェーイ!
さてruby版はポート9292番、perl版は5000番で立ち上がるわけです。

こいつらの間にKageをはさみます。

require 'kage'

def compare(a, b)
  if a != b
    p 'Unmatch responses!'
    p a
    p b
  end
end 

Kage::ProxyServer.start do |server|
  server.port = 8090
  server.host = '0.0.0.0'
  server.debug = false

  server.client_timeout = 15
  server.backend_timeout = 10

  server.add_master_backend(:production, 'localhost', 9292)
  server.add_backend(:sandbox, 'localhost', 5000)

  server.on_select_backends do |request, headers|
    if request[:method] = 'GET'
      [:production, :sandbox]
    else
      [:production]
    end
  end

  server.on_munge_headers do |backend, headers|
    headers['X-Kage-Session'] = self.session_id
    headers['X-Kage-Sandobox'] = 1 if backend == :sandbox
  end

  server.on_backends_finished do |backends, requests, responses|
    compare(responses[:production][:data], responses[:sandbox][:data])
  end

end

ドキュメント通りです。ちょっとポート番号とか比較部分変えてますけれど。
これで8090番にアクセスする度にどちらのサーバにも配信されます。master_backendにはruby版を指定しているので常にruby版が返ってきます。
この場合は例えばperl版を「Hello, ruby」にしてもServerヘッダとかそのへんが違うので結局Unmatchになっちゃうんですが、どっちもruby版にすればUnmatch出ません。こんなかんじで次デプロイするやつがおかしくないかとかちゃんと挙動が一緒かとかチェックできるんですね!

素晴らしいですね!!!!

ちなみに今回がんばってRuby書きましたけれど、実はPerl版を@さんが書いています。
思い立ってKageをPerlで書いてみた : D-7 <altijd in beweging>

こっちは試していませんが、僕はPerlがメインなのでもうちょっと遊びたくなったらこっちも試してみます!


というわけでみなさん、もっと安全に継続的に本番化、してみませんか。

追記

どっちかっていうとこういうの、継続的デリバリーになるんですかね