LaravelのセッションをHeroku Redisに保存する


LaravelアプリのセッションをHeroku Redisに保存する設定する手順についてまとめてみます。

HerokuでRedisを利用する場合、現在(2019.11)は公式のHeroku Redisを利用できます。

公式ドキュメントはこちら: Heroku Redis | Heroku Dev Center

セッションをキャッシュに入れるのはなぜか?

ところで、改めてHerokuでセッションをRedisなどのストレージに保存する必要があるのか?ってことなんですが、試しにfree Dynoを使っていてすぐにDynoがsleepしてしまうような場合は、DynoのファイルシステムはEphemeral Disk(揮発性ディスク)なのでRedisなどに保存しておかないとsleepするたびにセッションが切れてしまいます。
また、Hobby以上のDynoの場合でも1日一回は再起動されるとのことなのでやはりキャッシュストレージに入れておいた方が良さそうです。
参照: Restarting | Dynos and the Dyno Manager

一方、1日1回くらいならまあいいかとしてDynoが複数の場合はでは必要なのか?って話ですが、セッション固定機能のSession Affinityを使えば問題ないかもしれません。

とはいえよくわからないタイミングでセッションが切れるのは嫌なので、やはりセオリー通りセッションはRedisなどのストレージに保存しておくのがBetterなのではと言ったところです。

いまいち歯切れがわすいですが。。

セッションストレージをHeroku Redisに設定する手順

まずは、Heroku Redisアドオンを追加

$ heroku addons:create heroku-redis
Creating heroku-redis on ⬢ xxxxxx-xxxxx... free
Your add-on should be available in a few minutes.
! WARNING: Data stored in hobby plans on Heroku Redis are not persisted.
redis-deep-37043 is being created in the background. The app will restart when complete...
Use heroku addons:info redis-deep-37043 to check creation progress
Use heroku addons:docs heroku-redis to view documentation

アドオンをインストールすると環境変数REDIS_URLが追加されます。

$ heroku config | grep REDIS
REDIS_URL:                     redis://h:p26678e703cdfcb924c874797e6bfa151da85bfe0a2e24d410ff29f911b6d96d7@ec2-3-234-12-25.compute-1.amazonaws.com:25129

続いて、Laravel側の設定をしていきます。

Redisのドライバーを追加します。

$ composer require predis/predis

Herokuの環境変数で、セッションドライバーをredisにセットします。

$ heroku config:set SESSION_DRIVER=redis

次にRedisの接続情報を設定します。

Redisの接続情報は、config/database.phpredisの箇所で環境変数 REDIS_HOSTREDIS_PASSWORDREDIS_PORT から値を取得しています。

// config/database.php
    'redis' => [

        'client' => env('REDIS_CLIENT', 'predis'),

        'options' => [
            'cluster' => env('REDIS_CLUSTER', 'predis'),
            'prefix' => Str::slug(env('APP_NAME', 'laravel'), '_').'_database_',
        ],

        'default' => [
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_DB', 0),
        ],

        'cache' => [
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_CACHE_DB', 1),
        ],

    ],

ところで、Heroku Redisはメンテナンスでインスタンスが切り替わることがあり、切り替わった場合は自動でREDIS_URLの値も更新されます。つまりHeroku Redisアドオンを追加時にセットされたREDIS_URLを分解して値を直接上記の環境変数にセットするのはNGで、config/database.phpファイルの先頭でREDIS_URLを分解して各環境変数にセットするロジックを入れておくのが良いようです。
(この情報についてはHerokuのドキュメントなど一次ソースを探しましたが見つかりませんでした、経験則による情報なります。)

// config/database.php
<?php

use Illuminate\Support\Str;

if (getenv('REDIS_URL')) {
    $url = parse_url(getenv('REDIS_URL'));
    putenv('REDIS_HOST='.$url['host']);
    putenv('REDIS_PORT='.$url['port']);
    putenv('REDIS_PASSWORD='.$url['pass']);
}

return [
    ...
];

以上で設定完了です。

参考

, ,