<-- mermaid -->

深い階層にあるサーバーに対してスティッキーセッションを有効にするのが大変だった話

こんにちは。 NewsPicksの鶴房です。

前回のテックブログでは、テストの技法の話をしました。

(前回のテックブログはこちらから) tech.uzabase.com

早いもので、そこから1年経ちましたが、今回はAWSのスティッキーセッションに関する話をしようと思います。
ググっても日本語情報が見つからなかった内容なので、ニッチにな内容になりますが、同じことで困っている方がいればきっとお役に立てる内容かと思います!

尚、該当部分でも注意喚起をしていますが、今回の内容はAWSのサポートが保証する使い方でないものを含んでいます。 今回の内容に関して、AWSサポートより、推奨しないけど、多分実現可能だから自己判断して使ってね。という趣旨の回答をいただいています。 ビジネス利用される際は、AWSのサポートの方とよく話し合って、適切に利用するようにお願いします。

スティッキーセッションの説明

まず大前提となるスティッキーセッションの説明です!
一言で言えば、スティッキーセッションとは、[サーバーがスケールしていて複数個ある場合に、一つのセッションが有効な間は、そのクライアントとサーバーを常に一対一で接続させるロードバランサーの機能]です。
AWSではELBとターゲットグループがその機能を担っています。
ざっくりした説明になってしまったので、詳しくは下記をお読みください。

e-words.jp

docs.aws.amazon.com

経緯

今まで

NPでは、AWSのECSを利用しています。そして、歴史的な経緯もあり、APIサーバーに対するスティッキーセッションを有効にしています。
(一般論としてはECSの各コンテナは完全にステートレスな状態にして、スティッキーセッションを利用しない構成が望ましいですが、インメモリキャッシュへの依存度が高く、そのような構成にすることは難しい状態です。)

これを有効にするために、2022年初頭までは、 Client -> ELB -> サーバー の単純な構成だったので、ELBとターゲットグループの設定で [スティッキーセッションを有効にする] 、にチェックを入れておくだけでした。

新基盤の導入

ここで、NewsPicksのWebのフロントエンドのリアーキテクチャの話が出てきます。 2013年ごろから続けてきた、ThymeleafとCoofeeScriptで書かれたフロントエンドの拡張性に限界がきたので、nextjs + graphql で置き換えることとなりました。

下記ページなどはリアーキ後のページです。 特集:NewsPicksオリジナル記事

(応答速度も爆速になり、開発もしやすくなってリアーキテクチャは大成功でした。が、今回のブロ内容の本筋ではないので、軽く紹介するにとどめます。(いずれ誰かがブログを書いてくれるかと思うので、良かったらまた見に来てくださいね!)

さて、ここで、nextjsのサーバー(以下webサーバーと呼びます) とgraphqlサーバー( BackendForFrontendでBFFサーバーと呼んでいるので、以下BFFサーバーと呼びます。 )が挟まったことで、リクエストの経路が以下のように変更になりました。

変更前 : Client -> ELB -> APIサーバー
変更後 : Client -> ELB -> web(nextjs) -> ELB -> BFF(graphql) -> ELB -> APIサーバー

課題

ELBを複数回通る場合のスティッキーセッションの挙動

上記の変更後の状態では、通信がELBを複数回通過しています。 この場合、普通にスティッキーセッションを設定 (AWS公式ドキュメントが言うところの期間ベースのCookieに当たります) すると、一番浅い階層でしかスティッキーセッションが有効になりません。

これは、スティッキーセッションの維持のために、AWSALB というCookieを利用しているためです。
複数レイヤーのELBを通過する場合は、この名前空間がバッティングしてしまいます。

解決策

一番深い階層のAPIサーバーのターゲットグループでのみ、アプリケーションベースのCookieを有効にすることで、この問題を解決できました。

アプリケーションベースのCookieとは、APIサーバーが付与した特定のCookieに基づき、スティキーセッションの維持を行う設定になります。 この設定をすると、AWSALBAPP-{n} (nには0,1,2,と数字が入ります。)と言う名前のCookieがELBによって設定されます。

これにより、より浅い階層にあるELBではスルーされ、一番深い階層のELBでのみスティッキーセッションが有効になります。

再掲になりますが、詳しくは公式ドキュメントをお読みください。 また、この方法で複数階層のELを通る場合にスティッキーセッションを維持することに関してAWSサポートに問い合わせたところ、積極的に推奨はしないとのことでしたので、利用される場合は各自の判断でお願いします。 docs.aws.amazon.com

終わりに

以上が今回行った修正の概要になります。

ここで、今回の作業で大変だったことに関して書き残しておこうと思います。

記事にしてみると結論は「AWSの設定を変更しよう!」と言うことで、簡単な話ですが、開発当時は大変でした。 AWSの公式ドキュメントの日本語版は機械翻訳で読みづらいこともあり、場合によっては英語を読んで仕様を正確に理解し、その上で、不透明な部分関しては、一つ一つ設定を試しながら、ELBの内部仕様を探る感じで、調査を続けました。 ブラックボックスなものを推測していく感じで、楽しくはありましたが、私がバックエンドエンジニアながらインフラ系の仕事に手を出した矢先の仕事だったので、大変でした。

そして、日本語で同様のことをおこなっている記事は見つけられなかったので、誰かの役に立てればと思い、この記事を執筆しました。 同じような苦労をしている方がサクッと情報を獲れれば幸いです。

また、今回のスティッキーセッションのリリースに当たっては、

いかに、既存のユーザーへの影響を最小化しつつ、スティッキーセッションの方式を変更するか、とか
いかに、無停止でスティッキーセッションの設定を切り替えるか

などの他の課題もあり、それぞれ苦労したのですが、記事が冗長になるので、また機会があれば寄稿させていただきたいと思います!

最後に、NewsPickではエンジニアを募集しています! 私のようにバックエンドが主体のエンジニアでも、希望次第でAWS周りの難しい仕事を任せてもらえたりと、個々人の希望を叶えてくれる素敵な職場です。

このブログを最後まで読んでくれた学習意欲の高い方の応募をお待ちしております!

Page top