【AWS】ELBのスティッキーセッションを使い「アップロードしたファイルが消える」に対処した話

【AWS】ELBのスティッキーセッションを使い「アップロードしたファイルが消える」に対処した話

fukasawaです。こんにちは。クリスマスイブですね。
つぼログ。のtanakaさんから頂いた熊鈴が机の上にあるのを見て、シャンシャン鳴らしつつ、そこいらを駆けずりまわる光景が一瞬頭をよぎったのですが、そんなキャラでもないことを思い出したので自重しておこうと思います。

最近、携わっているシステムがVPSからAWS環境に移行したのですが、以前と環境が違うこともありちょこちょことトラブルが発生しています。今回はそのトラブルのうちの1つについて書いてみようと思います。AWS初心者ということもあり若干手探りなので、公式ドキュメントの方も合わせて目を通していただけると幸いです。

現象

不具合が発生したのは、とあるシステムの管理画面です。管理画面にはメールを一括送信する機能があり、添付ファイルを付けてメールを送れるようになっているのですが、その添付ファイルがメール送信時に消えてエラーになってしまうという現象でした。それも、毎回発生するわけではなく「ちゃんと送れるときもある」という状態です。

原因

原因ですが、AWS環境に移行しELBを導入したことによって発生するようになった不具合でした。
メール一括送信画面は、

[メール送信対象を選択]→[入力画面]→[確認画面]→[メール送信完了画面]

という画面遷移をします。
この[確認画面]→[メール送信完了画面]の間で添付ファイルが消えてしまっていました。

[入力画面]で添付されたファイルは、一時ファイルとしてAPサーバに内に保存されます。このときのアクセスがELBによってAPサーバ1に割り振られた場合はAPサーバ1に保存されますが、次の[確認画面]から[メール送信完了画面]への遷移でELBがAPサーバ2にアクセスを割り振ってしまった場合、APサーバ1に保存されたファイルが参照できなくなってしまいます。これによりプログラムが「ファイルが消えた」と判断し、エラーになっていました。

20151224_fukasawa_01.png

20151224_fukasawa_02.png

今までは、ロードバランサを使わずDNSラウンドロビンを使用して負荷分散を行っていたので問題になっていなかったようです。
ELBが悪いわけではなく、既存の問題がELBを導入したことによって出てきてしまったという感じでしょうか。

解決方法

ELBにはスティッキーセッションという機能があります。簡単に言うと「特定のCookieを持っている間はずっと同じインスタンスにアクセスを割り振ってくれますよ」という機能です。今回はこの機能を使用して解決を試みました。

※一時ファイルをAPサーバに置かずDBに突っ込んでしまう等、どこか別の場所に置くようにした方が良い気もするのですが、今回は少人数しか使用しない管理画面なので、負荷分散のことはあまり気にせずスティッキーセッションで対処することにしました。

① 期間ベースのセッション維持

AWSが発行するCookieを使用します。Cookieが存在する間(有効期限の間)は、ELBが同じインスタンスに繋がるようにしてくれます。プログラムの修正は不要です。(設定手順が↑のリンク先に書かれています。)

② アプリケーション制御によるセッション維持

アプリケーション側で発行する独自のCookieを使用します。Cookieが存在する間(有効期限の間)はELBが同じインスタンスに繋がるようにしてくれます。既に使用しているCookieを使う場合はプログラムの改修は不要ですが、新しいCookieを使用する場合は、Cookieを発行する処理を追加する必要があります。

ちなみに、アクセスしているインスタンスが落ちた場合は、別の有効なインスタンスにアクセスを割り振ってくれるみたいです。

今回は、②の方法を使用しました。

AWSコンソールでの設定

手順は下記のリンク先を参照してください。AWSコンソールからELBの設定画面に遷移し、スティッキーセッションで使用するCookie名を指定します。

プログラムの改修

新しくCookieを発行するよう修正します。ログインと同時に以下のCookieを作成するようにしました。
既に使用しているCookieを使おうと思ったのですが、CakePHPが発行するCookieの名前が「CakeCookie[xxx]」という形式になっており、使用できない文字([])が含まれているなどの問題があったので、新しいCookieを作成しました。

setcookie('awselb', 'awselb', null, '/kanri');
  • awselb : Cookie名。AWSコンソールで設定したCookie名と合わせてください
  • クッキーの値は任意

管理画面でのみ使用するので、管理画面のパス「/kanri」を指定しています。
画面によってはCookieの作成・削除を細かく行い、負荷分散に影響のないよう注意する必要があるとは思いますが、今回は管理画面なのであまり気にせず、ログインとともに無期限のCookieを発行しました。

動作確認

各APサーバにtext.htmlを配置します。APサーバ毎にtext.htmlの中身を変更し、Cookieが存在する間は「http://xxxxxxxx/kanri/test.html」でアクセスした際に同じ内容が返ってくるかを確認します。
Cookieが存在する間は同じ内容が返され、Cookieを削除するとバラバラの内容が返ってくる、という動きが確認できれば正しく設定されているはずです。

まとめ

他のシステムではどのように対処しているのでしょうか。

参考

  • このエントリーをはてなブックマークに追加

この記事を読んだ人にオススメ