Rails4 でセッションストアに DynamoDB を使う

rails
92件のシェア(ちょっぴり話題の記事)

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

2ヶ月以上前ですが、Rack アプリケーションで DynamoDB を セッションストア用として使うための gem が公開されていました。
DynamoDB Session Store for Rack Applications

Rails だと ActiveRecord のセッションストアがありますが、RDB なので、どうしても気になるのは負荷と障害ですね。
そんな時は、スケーラブルかつ耐障害性に優れた DynamoDB を使って解決しましょう。 *1

ということで、Rails4 で DynamoDB をセッションストアとして使う方法を試してみました。

Rails アプリケーションの作成

先ずは Rails アプリケーションの作成です。

$ mkdir try_dynamodb_sessionstore && cd try_dynamodb_sessionstore
$ bundle init
$ vim Gemfile
# A sample Gemfile
source "https://rubygems.org"

gem 'rails', '4.0.1'

$ bundle install --path vendor/bundle
$ bundle exec rails new . --skip-bundle

作成出来たら、今回対象の aws-sessionstore-dynamodb という gem を追記して、bundle install しましょう。

$ vim Gemfile
gem 'aws-sessionstore-dynamodb'

$ bundle install

各種設定

bundle install が終わったら、Rails の起動時に AWS の設定を読み込むように以下を記述します。

$ vim config/initializers/aws.rb
AWS.config({
  access_key_id: YOUR_ACCESS_KEY_ID,
  secret_access_key: YOUR_SECRET_ACCESS_KEY,
  region: YOUR_REGION
})

次に session_store.rb を開いて、セッションストアに DynamoDB を使うように指定します。

$ vim config/initializers/session_store.rb
# Be sure to restart your server when you modify this file.

TryDynamodbSessionstore::Application.config.session_store :dynamodb_store  

マイグレーション

Generator が用意されているので、以下のように実行すると、migration ファイルと設定ファイル dynamodb.yml が作られます。

$ bundle exec rails g sessionstore:dynamodb
      create  db/migrate/20131024152038_sessionstore_migration.rb
      create  config/sessionstore/dynamodb.yml

これで rake db:migrate を実行すると、実際に DynamoDB に作られるはずです。

$ bundle exec rake db:migrate
==  SessionstoreMigration: migrating ==========================================
==  SessionstoreMigration: migrated (57.4941s) ================================

マネージメントコンソールを開くと、DynamoDB に sessions という名前のテーブルが作られていますね。

131025-0002

コントローラとビューの作成

セッションの動きを確認するために、シンプルなコントローラとビューを作ります。

$ bundle exec rails g controller blogs --no-helper --no-assets —no-test-framework 

Controller

app/controllers/blogs_controller.rb

class BlogsController < ApplicationController

  # GET /blogs
  def index
    if session[:counter].nil?
      session[:counter] = 1
    else
      session[:counter] += 1
    end
  end

end 

View

app/views/blogs/index.html.erb

<p><%= session[:counter] %></p> 

Routes

config/routes.rb

root 'blogs#index'

counter をカウントアップして、表示するだけのサンプルを作りました。

セッションの動きを確認する

ここまで終わったら、Rails を起動して、ブラウザ(http://localhost:3000/)でカウンターが増えることを確認しましょう。

$ bundle exec rails s

ブラウザで確認できたら、マネージメントコンソールを見てみると、アイテムが作られてるのが分かりますね!

131025-0003

属性として、session_idcreated_atdataupdated_at がありますが、これは後述のセッション削除の条件の部分でポイントになります。

セッションデータの削除

DynamoDB に登録されるセッションデータの削除は rake タスクとして用意されているのでこれを使います。

$ bundle exec rake -T db:sessions 
rake db:sessions:cleanup  # Clean up old sessions in Amazon DynamoDB session store

実行して、セッションデータを削除します。

$ bundle exec rake db:sessions:cleanup

マネージメントコンソールを確認してみると、アイテムが削除されてるのが分かりますね!

131025-0005

セッション削除の条件を指定する

dynamodb.yml にある max_agemax_stale を指定すると、上記の rake タスクで削除される条件を設定できます。

$ vim config/sessionstore/dynamodb.yml
・・・
# [Integer] Maximum number of seconds earlier
# from the current time that a session was created.
# By default this is 7 days.
#
max_age: 604800

# [Integer] Maximum number of seconds
# before the current time that the session was last accessed.
# By default this is 5 hours.
#
max_stale: 18000
・・・

max_agemax_stale は、DyanmoDB 上に作成された Item の属性である created_atupdate_at に各々対応しており、 指定した期間を過ぎている Item だけが、rake db:sessions:cleanup の際の削除対象になります。

参考サイト

aws / aws-sessionstore-dynamodb-ruby

脚注

  1. このあたりの話は以下のリンクが参考になりますです。
    Amazon DynamoDBによるTomcatセッション永続化とフェイルオーバー

AWS Cloud Roadshow 2017 福岡