今更ながら、複数台サーバーに対応させるためsession管理をmemcachedを使って外部化したいと思います。
Require
- rails 4
- unicorn
- memcached
- osx
なんでmemcached
以前はredis-storeを使ってみたのです。
レプリもできるし、複雑な型も扱えるからredisがいいなーと思っているので幸せが待っている臭いがします。
が、最近更新滞ってるし、、、っていう後ろ向きな理由でdalli + memcachedです。
Install memcached and setup launchclt
とりあえず入れる
$ brew install memcached
memcached: stable 1.4.20 (bottled)
http://memcached.org/
Conflicts with: mysql-cluster
/opt/boxen/homebrew/Cellar/memcached/1.4.20 (10 files, 184K) *
Built from source
From: https://github.com/Homebrew/homebrew/commits/master/Library/Formula/memcached.rb
==> Dependencies
Required: libevent ✔
==> Options
--enable-sasl
Enable SASL support -- disables ASCII protocol!
--enable-sasl-pwdb
Enable SASL with memcached's own plain text password db support -- disables ASCII protocol!
==> Caveats
To have launchd start memcached at login:
ln -sfv /opt/boxen/homebrew/opt/memcached/*.plist ~/Library/LaunchAgents
Then to load memcached now:
launchctl load ~/Library/LaunchAgents/homebrew.mxc
書いてある通りlaunchdCtlで自動起動設定
$ ln -sfv /opt/boxen/homebrew/opt/memcached/*.plist ~/Library/LaunchAgents
$ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.memcached.plist
確認
# プロセス
$ ps axu | ag memcached
foo 84598 0.0 0.0 2464188 380 ?? S 9:16PM 0:00.06 /opt/boxen/homebrew/opt/memcached/bin/memcached -l localhost
# 繋げる
$ telnet localhost 11211
stats
...
ok
rails側に設定
memcache clientはdalliを利用します
$ vim Gemfile
gem 'dalli'
$ bundle
とりあえずdevelopモードで動くようにします。
cacheとsession設定をdalli経由に変更
$ vim config/environment/development.rb
AppName::Application.configure do
...
config.cache_store = :dalli_store
...
$ vim config/initialize/session_store.rb
FooRails::Application.config.session_store ActionDispatch::Session::CacheStore, key: '_foo_session', expire_after: 1.month
consoleでcacheテスト
$ rails c
pry> Rails.cache.write 'foo', 'bar'
Cache write: foo
Dalli::Server#connect 127.0.0.1:11211
=> 144115188075855872
pry> Rails.cache.read 'foo'
Cache read: foo
=> "bar"
ok
deploy後に再接続
dalli 2.0.4から再接続は不要です
https://github.com/petergoldstein/dalli/issues/208
unicornのafter fork時に、memcachedとのコネクションを張り直します。
after_fork do |server,worker|
...
if defined?(ActiveSupport::Cache::DalliStore) && Rails.cache.is_a?(ActiveSupport::Cache::DalliStore)
Rails.cache.reset
ObjectSpace.each_object(ActionDispatch::Session::DalliStore) { |obj| obj.reset }
end
環境変数の外だし
最終的にはElasticCacheへの接続したい物の、VM内での構築試験するためにわざわざEC2経由するとかしたくないので、dotenv gemを利用して設定を外部化します。
.evn設定
$ vim .env
# nil is connecting to local memcached
CACHE_STORE=nil
環境変数引っ張る様に変更
# developから外して
$ vim config/environment/development.rb
- AppName::Application.configure do
- ...
- config.cache_store = :dalli_store, ENV['CACHE_STORE']
- ...
# productionのみ追加
$ vim config/environment/production.rb
AppName::Application.configure do
...
config.cache_store = :dalli_store, ENV['CACHE_STORE']
こんな感じで。