はじめに
Oracle Cloud Infrastructure(以下OCI) で提供している Load Balancer には、Session Persistence と呼ばれるバインド機能があります。
Session Persistence を使うことによって、Load Balancer にアクセスしてきたユーザーのリクエストを、前回アクセスしたバックエンドサーバーにバインドすることが可能です。
AWS の ELB でいうと、スティッキーセッションと似た機能となっています。
概要
- 初めてアクセスしてきた client に、特定の値を持つ cookie を設定
- 2回目以降のアクセスを行った時に、特定の値を持つ cookie を確認して、前回アクセスしたバックエンドサーバーへリクエストをバインドする
アプリケーションの構成によっては、前回アクセスしたサーバと同一なものへアクセスし続けることが必要になります。
例を挙げると、セッション管理をローカルで行う、ファイルをローカルに生成している、といったことが考えられます。
モダンなアプリケーションの構成では、こういったローカル管理はやめてステートレスにしていくことが望ましいですが、様々な理由からアプリケーションの変更が出来ない事も多いです。
このような時に、Session Persistence 機能を使うことで、便利に負荷分散していくことが可能です。
前提作業
OCI環境
以下の環境をすでに OCI で作成済みです。
- Compute Instance 2台
- CentOS7
- Load Balancer
バックエンドサーバーで Cookie のログ出力
Session Persistence の機能自体を使用するには、特別な設定は バックエンドサーバーには不要です。
今回は、バックエンドサーバー側でどのような Cookie を受信したか確認したいので、Golang で Webサーバーを構成して、Cookie の内容を標準出力へ出力するプログラムを書きます。
Golang install は以下の記事を参考に適当に導入します
https://qiita.com/sugimount/items/1e677f1beab747959b81
Cookie の内容を標準出力へ出力するプログラムは、Github で公開しています
https://github.com/Sugi275/sample-go-cookie
ソースコードは以下の通りです。
package main
import (
"fmt"
"log"
"net/http"
)
// cookieの設定+標準出力へプリント
func setCookies(w http.ResponseWriter, r *http.Request) {
cookie := &http.Cookie{
Name: "hoge",
Value: "bar",
}
http.SetCookie(w, cookie)
fmt.Fprintf(w, "Hello Cookie!")
cookies := r.Cookies()
fmt.Println("start")
fmt.Println(cookies)
fmt.Println("end")
}
// メイン
func main() {
http.HandleFunc("/", setCookies)
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
Golang をインストール済みの Linux 環境で、以下のように簡単に実行することができます。
OCI 上に作成した、Compute Instance 2台で以下のコマンドを実行します。
cd ~
git clone https://github.com/Sugi275/sample-go-cookie.git
cd ~/sample-go-cookie
./sample-go-cookie
上記を実行すると、8080番ポートで Webサーバーが立ち上がります。ブラウザを使用して、Compute Instance の Public IP にアクセスを行うと、以下のWebページが表示されます。
Chrome のデベロッパーツールで Cookies を表示すると、Golang 上で SetCookie した内容が確認できます。
Goのプログラム上で、Cookie の内容を標準出力へ出力した結果は、以下の内容が表示されています。
[opc@web01 sample-go-cookie]$ ./sample-go-cookie
start
[hoge=bar]
end
Session Persistence の設定
前提作業で構成した、OCI Load Balancer の詳細画面へ移動します。
Backend Sets の Edit を選択します。
ENABLE LOAD BALANCER COOKIE PERSISTENCE
を選択して、Save Changes を押します。
選択肢の説明をします。
- DISABLE SESSION PERSISTENCE : Session Persistence を無効にする
- ENABLE APPLICATION COOKIE PERSISTENCE : バックエンドサーバー側で、Cookie を作成するオプション。細かな制御を行いたい場合はこちらを選択する
- ENABLE LOAD BALANCER COOKIE PERSISTENCE : Load Balancer 側で、Cookie を作成するオプション。基本的にはこちらを使用すると思う。Cookie NAME や、Cookie の有効期間などを指定することが可能
Session Persistence 動作確認
アクセス確認
Load Balancer を経由して、バックエンドサーバーにアクセスして、Chrome の Developper Tools を確認します。
Session Persistence 時に、COOKIE NAME
を空白にしたので、Default の X-Oracle-BMC-LBS-Route
というName の Cookie が生成されています。Value は Load Balancer 側で生成されたランダムの値が入っています。
このランダムの値を使用して、どこのサーバーにバインドするべきかを管理されている動きになります。
Golang 側の標準出力を見ると、以下のような出力となっています。こちらの結果でも、X-Oracle-BMC-LBS-Route
の Cookie を確認することが出来ます。
Web01 バックエンドサーバー側でも正しく、Load Balancer で自動付与された Cookie を確認することが出来ます。
[opc@web01 sample-go-cookie]$ ./sample-go-cookie
start
[X-Oracle-BMC-LBS-Route=cfc5eecb841cac84444ddf07c6db58e9b8ac77fc hoge=bar]
end
Cookie が Expire しない限り、何度アクセスしても前回アクセスしたバックエンドサーバーへバインドされます。
Cookie 削除して確認
Cookie を削除して、アクセス先のサーバーや、Cookie の値が変更することを確認します。
Chrome で、以下の黄色い箇所をクリックします
Cookie を選択します
削除して、完了を押します。
再度 Chrome からアクセスします。Value の値が先ほどと変わっています。
バックエンドサーバー側の標準出力を見ると、先ほどまでWeb01 でしたが、Web02 側に切り替わりました。
[opc@web02 sample-go-cookie]$ ./sample-go-cookie
start
[X-Oracle-BMC-LBS-Route=bd28576df4f98e0ed1f460613b3a1a6a1f93a09b hoge=bar]
end
フェールオーバー動作確認
今は Web02 側でバインドされています。では、このときに、Web02側に障害がおこるとどうなるのでしょうか。
答えは、正常に動作しているWeb01 側にフェールオーバーします。この時に、Cookie も再度作成されます。
では、Web02 で動作している Golang を停止して、再度アクセスを行います。
以下の表示結果のように、Value がまた変わっています。
バックエンドサーバー側を確認すると、Web01 側で以下のログが表示されています。
[opc@web01 sample-go-cookie]$ ./sample-go-cookie
start
[X-Oracle-BMC-LBS-Route=bd28576df4f98e0ed1f460613b3a1a6a1f93a09b hoge=bar]
end
参考URL