愛雅小鋪

安裝與設定 HAProxy

HAProxy 是一套 TCP/HTTP Load Balancer. 原本想說 nginx 似乎終於要支援 proxy websocket 了, 結果 1.2 釋出後還是搞不定, 於是決定跳槽… 應該說是加入新的工具, 因為 HAProxy 沒辦法完整取代 nginx. HAProxy 提供了很完整的 proxy 能力, 不過它並不是 web server, 所以沒有 serve static file 的能力, 所以 nginx 就變成 serve static file 專用的 server 了… XD

安裝

在 Arch Linux 下要從 AUR 安裝, 我用 yaourt:

1
$ yaourt -S haproxy

設定

打開 /etc/haproxy/haproxy.cfg 你會看到 global, defaults 和一堆 listen, 由於本文只打算作為快速入門用, 就不詳細解釋這些東西在幹嘛了 (懶 + 很多還不知道 XD).

事前

listen 區塊是結合 frontendbackend 功能的區塊, 你可以在這裡把 header 解析和 backend server 一起設定, 不過我的需求有點複雜, 所以還是 frontendbackend 乖乖分開寫… 所以先砍掉所有的 listen 區塊吧!

為了測試, 請先把 global 中的 chroot, uid, gid, daemon 關掉 (使用 # 開頭表示註解), 並打開 debug.

nginx backend + virtual hosts 設定

我們打算讓 nging serve static file, 以這個 blog 來說就是把所有來自 ayaya.tw 的請求都往 80 port 丟.

在前端我們想要 listen 8080 port, 所以寫一個 frontend 區塊:

1
frontend all 0.0.0.0:8080

接著, 寫下比對的條件:

1
2
3
frontend all 0.0.0.0:8080
  acl is_blog hdr_beg(Host) -i ayaya.tw
  use_backend static if is_blog

acl 指令在符合指定條件 (hdr_beg(Host) -i ayaya.tw) 時, 會將指定的值 (is_blog) 設定為 true.

在這裡我給的條件是: 當 header (hdr) 中的 Host 欄位以 ayaya.tw 開始 (beg) 時, 將 is_blog 設定為 true. -i 則表示無視大小寫.

下一行看起來就很 ruby: 如果 is_blog 就使用 static 這個 backend.

所以來設定 static 這個 backend:

1
2
3
4
backend static
  timeout server 30000
  timeout connect 4000
  server static01 127.0.0.1:80 check

static01 是我給 server 取的名字, 它的位置在 127.0.0.1:80, check 則是告訴 HAProxy 定時檢查 server 狀態, 預設是用 OPTIONS / 檢查, 你可以使用 option httpchk 改以其他 method/path 檢查.

透過以上的設定, 就可以將 http://ayaya.tw:8080 導至 server 本機的 127.0.0.1:80.

啓動

1
haproxy -f /etc/haproxy/haproxy.cfg

這個時候就可以連上 ayaya.tw:8080 試試看能不能正確取得檔案了. 沒有問題的話, 就可以和 nginx 互換 port 讓 HAProxy 跑在前面了.

1
$ sudo /etc/rc.d/haproxy start

別忘了打開 global 中的 chroot, uid, gid, daemon, 關掉 debug

Snippets

WebSocket

WebSocket 需要比較持久的連線, 所以在 backend 中將時間拉長…

1
2
3
4
5
6
7
8
9
frontend
  acl is_websocket hdr(Upgrade)  -i WebSocket
  acl is_websocket hdr_beg(Host) -i ws
  use_backend your_websocket_backend if is_websocket

backend
  timeout queue 5000
  timeout server 86400000
  timeout connect 86400000

讓 backend 保有 client ip

不設定這個的話, backend 永遠都會得到 HAProxy 所在的 ip address.

1
2
global
  option forwardfor

HTTP basic auth

LIST_NAME, USERNAMEPASSWORD 換成你喜歡的:

1
2
3
4
5
6
userlist LIST_NAME
  user USERNAME insecure-password PASSWORD

backend
  acl is_authenticated http_auth(LIST_NAME)
  http-request auth realm Who\ are\ you? if !is_authenticated

字串不能用引號包, 要用 \ escape 空白…

啓用 HAProxy 內建後台

把帳號密碼換成你喜歡的:

1
2
3
4
5
backend stats
  stats enable
  stats uri /
  stats realm Global\ statistics
  stats auth admin:1234

Hot-reconfigure

1
haproxy -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)
Comments

安裝與設定 Thinking Sphinx (含中文支援)

開發環境篇

環境:

  • Mac OS X
  • 使用 Homebrew
  • 使用 rvm, ruby 1.9.3, rails 3.1

安裝 Sphinx

1
brew install sphinx

安裝 Thinking Sphinx

in Gemfile:

1
gem 'thinking-sphinx'

然後 bundle install.

設定索引

看這裡

設定 Thinking Sphinx

首先加入中文支援, in config/sphinx.yml:

1
2
3
development:
  ngram_len: 1
  ngram_chars: "U+3000..U+2FA1F"

接著執行 rake ts:conf, 這個 task 會產生設定檔 config/[environment].sphinx.conf, 請不要加入 git, 因為這個檔案會包含 database.yml 的資訊, 因此請將它加入 .gitignore.

建立索引

執行 rake ts:index 後會建立索引, 並儲存於 db/sphinx/, 同樣的這個目錄也應該加入 .gitignore.

這個 task 需加入 crontab, 約半小時執行一次.

如果使用 whenever, 可在 config/schedule.rb 中加入:

1
every(30.minute) { rake 'ts:index' }

啟動 searchd

執行 rake ts:start, 若看到 Started successfully (pid xxxxx)., 表示順利啟動成功.

必須要啟動 searchd 才能進行搜尋, 否則會噴 Riddle::ConnectionError.

注意事項

若有變更資料庫或者索引, 必須執行 rake ts:rebuild 重新建立索引.

生產環境篇

環境:

  • Arch Linux
  • 使用 yaourt
  • 使用 rvm, ruby 1.9.3, rails 3.1
  • 使用 Capistrano

安裝 Sphinx

1
yaourt -S sphinx

設定 Thinking Sphinx

加入中文支援, in config/sphinx.yml:

1
2
3
production:
  ngram_len: 1
  ngram_chars: "U+3000..U+2FA1F"

設定 Sphinx 執行檔位置, in config/sphinx.yml:

1
2
3
4
5
6
production:
  ngram_len: 1
  ngram_chars: "U+3000..U+2FA1F"
  bin_path: /usr/bin/
  searchd_binary_name: sphinx-searchd
  indexer_binary_name: sphinx-indexer

設定 Capistrano

config/deploy.rb 中加入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace :deploy do
  namespace :thinking_sphinx do
    task :stop, :roles => :app do
      run "cd #{current_path} && RAILS_ENV=#{rails_env} bundle exec rake ts:stop"
    end

    task :restart, :roles => :app do
      run "cd #{release_path} && RAILS_ENV=#{rails_env} bundle exec rake ts:stop ts:rebuild"
    end
  end

  before 'deploy:update_code', 'deploy:thinking_sphinx:stop'
  after 'deploy:restart', 'deploy:thinking_sphinx:restart'
end

第一次 deploy 時得先拿掉 before 'deploy:update_code', 'deploy:thinking_sphinx:stop', 因為這個時候還沒有安裝 Thinking Sphinx, 會找不到 ts:stop 這個 rake task.

順便一提 ts:rebuild 也會順便把 searchd 開起來, 所以就不用再跑 ts:start 了.

Comments