LoginSignup
0
1

More than 5 years have passed since last update.

Memorystoreを使ってGAE/FEで動くSpringbootのセッションを管理する

Posted at

はじめに

Memorystore にGAE/FE(Java runtime)で動くSpringbootのセッションを管理させてみましたのでまとめます。

オープンソースのRedisとMemorystoreの差異は Memorystoreリファレンスのこのへん に記載されています。
はたしてすんなり動くのか?

TL;DR

Springのリファレンス の通り下記の指定をすれば動きます。

@Bean
public static ConfigureRedisAction configureRedisAction() {
    return ConfigureRedisAction.NO_OP;
}

Memorystoreでは CONFIGコマンドがブロックされている ため、この対応が必要になるようです。
Springのリファレンスによると上記の結果 SessionDeletedEventSessionExpiredEvent は取れなくなるとのこと。

上記以外の注意点として、MemorystoreとGAEは 同一プロジェクト、同一リージョン、同一ネットワークにないと接続できません

試してみる

上記を試してみます。

事前準備

まず下記が無ければ用意します。

Cloud SDKは 使用するアカウントとプロジェクトを指定してログイン しておきます。
また適当なSpringbootサンプルソースはGitHubにあげました

Memorystoreを起動する

GCPのウェブUIのMemorystoreのところでインスタンスを作成します。

設定は初期値の通りでいいですが、使用するプロジェクトでもし過去にGAEをデプロイした
ことがある場合は、GAEとMemorystoreのリージョンを合わせておく必要があります

GAEのリージョンはウェブUIのダッシュボードの右上か コマンドライン(describeのlocationId) で確認できます。

image.png

Memorystoreの起動が完了すると次の通りインスタンスに割り当てられたIPが確認できます。
image.png

適当なSpringbootサンプルソースについて

適当なサンプルはGitHubにあげました
以下サンプルの補足です。

サンプル画面

次の通り訪問回数をセッションに保存して表示するだけの画面を作りました。

HelloSpringbootController.java

@RestController
public class HelloSpringbootController {

    @RequestMapping({ "/" })
    public String index(HttpSession session) {

        Integer visits = (Integer) session.getAttribute("visits-by-session-key");
        visits = visits == null ? 1 : ++visits;
        session.setAttribute("visits-by-session-key", visits);

        return "visits by session => " + visits;
    }
}

画面を呼び出すと次のような感じ。
image.png

プロファイルの切替

ローカルと本番(GAE)のプロファイルの切替は app.yaml で環境変数 SPRING_PROFILES_ACTIVE を指定して行いました。
ローカルは指定無し、本番は'prod'を指定しています。

appengine/app.yaml
runtime: java
env: flex

handlers:
  - url: /.*
    script: this field is required, but ignored

resources:
  cpu: 1
  memory_gb: 2

# Specify the active profile of spring for production environment by environment variable.
env_variables:
  SPRING_PROFILES_ACTIVE: 'prod'

なお本サンプルで切り替えているのは application.ymlapplication-prod.yml だけです。

RedisのIPを指定する

先ほどのMemorystore起動時に割り当てられたIPを application-prod.yml で指定します。

resources/application-prod.yml
# Setting for production environment
spring:
  redis:
    host: 10.0.0.3
    port: 6379

ConfigureRedisActionを指定する

次のような感じ。

HelloSpringbootSessionConfig.java
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 60)
public class HelloSpringbootSessionConfig {

    @Bean
    public ConfigureRedisAction configureRedisAction() {
        return ConfigureRedisAction.NO_OP;
    }

    // イベントが飛んでくるかどうかを確認
    @EventListener
    public void confirmEvent(ApplicationEvent event) {
        System.out.println(LocalDateTime.now().toString() + " --> " + event.getClass().getSimpleName());
    }

}

修正点まとめ

素のSpringbootアプリをGAE + Memorystoreに載せるのに必要な修正点をまとめると次の通り。

修正(または追加)対象 補足
pom.xml appengine-maven-pluginを追加
app.yaml GAEの設定
HelloSpringbootSessionConfig.java ConfigureRedisAction.NO_OPを指定
application-prod.yml MemorystoreのIPを指定

GAEを初期化する

もし該当プロジェクトで過去にGAEを使用したことがない場合は、まず最初にGAEで使用するリージョンを指定します。
次の通りウェブUIで行うか、または コマンドライン で行います。
image.png

image.png

ここではGAEのリージョンの指定まで出来ればよいです。
GAEのリージョンはMemorystoreと合わせておく必要があります。
またGAEのリージョンは一度設定すると変更できません。

GAEにデプロイする

最後に > mvn appengine:deploy でデプロイします。

> mvn appengine:deploy
[INFO] Scanning for projects...
[INFO]
[INFO] ----------< com.example:hello-springboot-with-session-on-gae >----------
[INFO] Building hello-springboot-with-session-on-gae 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] >>> appengine-maven-plugin:1.3.2:deploy (default-cli) > package @ hello-springboot-with-session-on-gae >>>
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ hello-springboot-with-session-on-gae ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO] Copying 0 resource
(以下略)

以上でGAEにSpringbootアプリがデプロイされました。

アプリにアクセスしてみる

GCPのウェブUIからリンクをたどるか、または コマンドライン でブラウザを開きます。
image.png

以上で動作が確認できます。

参考までイベントが飛んで来たらわかるようにしました
ログを見るとリファレンス記載の通り SessionDeletedEventSessionExpiredEvent は飛んでないことが確認できます。

いやオレはイベント使うんじゃ・・という場合

MemorystoreではCONFIGコマンドはブロックされていますが、一部のconfig値はウェブUIほかで設定可能です。
これをちょっと試してみました。

Springのリファレンスを元に次の通りnotify-keyspace-eventsEgx をセットして・・

image.png

そしてブラウザでアクセス後にログを見てみると次のような感じ。
image.png

※ 今回試した環境ではGAEインスタンスが2台あり、SessionCreatedEventSessionExpiredEvent は2台とも受け取っているようでした。
※ またSessionDeletedEventはまったく見当たりませんでした。

以上です。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1