Hatena::ブログ(Diary)

lambda {|diary| lambda { diary.succ! } }.call(hatena) このページをアンテナに追加 RSSフィード

 | 

2012-01-28

[] EventMachineで簡単なロードバランサーを書いてみた

同期の問題は大変デスネー

Hostヘッダ渡さなくてもレスポンス返してくれたのがちょっと意外だった。

Hatena Blogはレスポンス返してくれるのかな?


#!/usr/bin/env ruby
require 'rubygems'a
require 'eventmachine'

class Backend < EM::Connection
  def initialize(proxy)
    @proxy = proxy
  end

  def receive_data(data)
    @proxy.send_data(data)
  end
end

class Proxy < EM::Connection
  def initialize(backends)
    # コネクション毎の生成なので、このタイミングでバックエンドを決める
    host, port = backends[rand(backends.length)]
    @backend = EM.connect(host, port, Backend, self)

    # プロセス内でグローバルなラウンドロビンをやろうと思うと
    # プールの同期が必要になって、パフォーマンスが低下する気がする
    #
    # "以前に言及したように、接続と接続の間で君のクラスのインスタンスはどんな情報も共有できない。
    #  幸運にも、いや、設計されたことだろうが、EventMachine はこれを処理するメカニズムを提供する。"
    # http://keijinsonyaban.blogspot.com/2010/12/eventmachine.html
    # 
    # 共有…まじめに同期しようと思うと大変な気がするなー
    # mutableなオブジェクトについてのソリューションもあるのかしら
    #
    # バックエンドのコネクションもプーリングできたらよいけど
    # EventMachineのパターンと相性悪いような…
    # まあProxyへの接続が維持されている間はコネクションも維持されるので
    # そんなに問題ではないのかも
  end

  def receive_data(data)
    @backend.send_data(data)
  end
end

EM.run do
  # 順序が大事!なのでHashは×(たぶん)
  EM.start_server('0.0.0.0', 80, Proxy, [
    ['www.yahoo.co.jp', 80],
    ['www.hatena.ne.jp', 80],
  ])
end

shell1> ruby lb.rb

shell2> for i in {1..5}
> do
> wget -q -O- 127.0.0.1 | nkf | fgrep '<title>'
> done
<title>はてな</title>
<title>はてな</title>
<title>Yahoo! JAPAN</title>
<title>Yahoo! JAPAN</title>
<title>はてな</title>

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

リンク元
 |