32
Wagbyのオートスケールに 関する技術情報 1/32 2019.7.18 Wagby R8.3.0 対応

Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

Wagbyのオートスケールに関する技術情報

1/32

2019.7.18Wagby R8.3.0対応

Page 2: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

OUTLINE•一般的なクラスタリング/オートスケール• Wagbyのクラスタリング• オートスケール対応の方針• CacheManagerの対応• セッション情報の共有• ジョブスケジューラーの対応

2/32

Page 3: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

クラスタリング

•一般的なクラスタリング• 複数台のアプリケーションを同時に可動させる

• 1台で障害が発生してもサービスは継続できる(可用性の向上)

• ロードバランサでアクセスを複数のアプリへ振り分ける(利用者は複数台を意識しなくて良い)

3/32

Page 4: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

オートスケール

•一般的なオートスケール• クラスタリングの考えに以下を加えたもの

• スケールアウト:稼働サーバーの台数を増やす• スケールイン :稼働サーバーの台数を減らす• オートスケール :サーバーの負荷に応じてスケールイン・アウトを自動で行う

オートスケール

4/32

Page 5: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

Wagbyのクラスタリング(R5.7.0+)

• RDBは一つ• セッションレプリケーションなし

• ロードバランサのStickySession機能を有効にする• 可動させるサーバーの数とIPアドレスを事前に決める

• 定義ファイルに記述

ロードバランサ

wagbyapp

wagbyapp

DB

StickySession

オンプレミス環境で、2台のサーバー運用を想定

※N台構成は可能だが、現実には2台が多かった

IPアドレス登録

5/32

Page 6: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

単一サーバー動作時との違い

• キャッシュ• 各サーバー間でキャッシュ情報を共有する

• クラスタリング時はサーバー間でJMX(JavaManagementeXtension)プロトコルを使った通信を行っていた• この通信には全稼働サーバーのIPアドレスが必要

• ロック• 悲観ロック情報を各サーバー間で共有する

• 単一サーバー動作時はメモリ上で管理• クラスタリング時はRDBで管理

• 楽観ロックは単一サーバーと同じ様に動作する• セッション情報の共有

• 共有は行わないため、ロードバランサでStickySession機能を有効にする• ログオン後は常に同じサーバーに振り分けられる必要がある• サーバーがダウンした時、このサーバーを使っていた利用者のセッション情報は失われるため、再ログオンが必要

6/32

Page 7: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

オートスケール対応の方針

• セッション情報の共有を行う• サーバーダウン時の再ログオンをなくす• ロードバランサのStickySession機能不要

• IPアドレスの事前設定を不要とする• IPアドレスに依存しない複数サーバー稼働を実現する

•課題解決にRedis、MQ(MessageQueueing)を活用• 複数サーバー間の情報共有にはこの2つの技術が一般的

7/32

Page 8: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

オートスケール対応の方針[2]• セッション情報の共有にRedisを利用• キャッシュ情報の共有にMQを利用• クラスタリング時はJMXを使っているが事前にIPアドレスの登録を必要するため、今回は利用しない

• その他、ジョブ機能、パスワードリマインダ機能などもオートスケール用の対応が必要

ロードバランサ

wagbyapp

wagbyapp DB

StickySession

パブリッククラウド環境で、2台以上のサーバー運用を想定

Redis

MQwagbyapp

wagbyapp8/32

Page 9: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

オートスケールの設定

(1)環境>サーバ>オートスケールの欄に用意された「オートスケールを有効にする」をチェックする

(2)環境>サーバ>アプリケーションの欄に用意された「ActiveMQ」を設定する。送信先は「ブローカー接続」とする。ブローカーURLとユーザ名、パスワードを指定する(ジョブを受信するキューの名前は空白とする)

9/32

Page 10: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

想定する利用方法

• Wagbyで開発した業務アプリケーションをパブリッククラウドで運用する(SoR分野での利用)

• WagbyでSoEのバックエンドを開発し、フロント層とRESTAPIでつなげる(SoRとSoEの連携)

10/32

Page 11: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

オートスケールに対応したWagby内部の仕組み

11/35

Page 12: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

CacheManager• データ取得• キャッシュなし:RDBから取得、キャッシュを作成• キャッシュあり:キャッシュを利用(RDBアクセスなし)

• データ登録・更新・削除• キャッシュを削除するのみ

RDB

CacheManager

DAO3.キャッシュがなければRDBアクセス

4.データを返す

5.キャッシュを作成・追加する

12/32

Page 13: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

CacheManager• Wagbyのキャッシュ対象一覧

対象 説明

ストアモデル (Entity) データベースから取得したストアモデルのキャッシュ詳細画面表示時や他モデル参照の解決に利用される

選択肢 画面に表示されるリストボックスやラジオボタン、チェックボックスの選択肢のキャッシュ

選択肢の絞り込み設定などが利用されている場合はキャッシュは作成されない

※一覧表示画面はキャッシュ対象外です。ただし一覧表示項目のモデル参照解決にはストアモデルのキャッシュが利用されます。そのため(N+1)問題の発生を抑えられるようになっています

13/32

Page 14: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

CacheManagerの問題点• オートスケール時の問題点• 複数サーバーで個別にキャッシュを管理• キャッシュが古くなっていることを検知できない

1. サーバーAの更新画面でデータを更新(RDBを更新)2. サーバーAのキャッシュはクリアされる3. サーバーBは更新に気づかず変更前のキャシュを保持したまま

RDBCache

Manager

DAO2.キャッシュを削除

サーバーA

CacheManager

DAO

古いキャッシュが維持されたまま

サーバーB

14/32

Page 15: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

CacheManagerの対応 [1]• Ehcacheが提供するレプリケーションの考え方

https://www.ehcache.org/documentation/2.7/replication/jms-replicated-caching.html15/32

Page 16: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

CacheManagerの対応 [2]• Wagbyは複数サーバー間のキャッシュの複製は行わない• キャッシュデータのコピーは通信コストが高い

•代わって、キャッシュ削除メッセージのやりとりのみを行う• キャッシュの作成は各サーバーに任せるがクリア処理だけは全サーバーで統一

• Ehcacheのオプション機能を利用することでキャッシュの複製はせずにクリア処理だけを共有することが可能

16/32

Page 17: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

CacheManagerの対応 [3]• キャッシュクリア処理の共有• ActiveMQ(メッセージキュー管理サーバー)• Publish/Subscribeメッセージング機能(1対nメッセージングモデル)

Publisher

データXXのキャッシュを削除

topic1.メッセージをtopicに登録

メッセージ

ActiveMQ

Sbscriber

Sbscriber

Sbscriber

2. topicに購読登録している全Sbscriberにメッセージ

を送信…

メッセージ

メッセージ

メッセージ

Wagbyアプリケーション

Wagbyアプリケーション

Wagbyアプリケーション

Wagbyアプリケーション

17/32

Page 18: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

CacheManagerの対応 [4]• Ehcache向け設定ファイル(WEB-INF/classes/ehcache.xml)

• 上記に加えメッセージサーバーの接続情報も定義する

<defaultCacheeternal="false"timeToIdleSeconds="600"timeToLiveSeconds="600"memoryStoreEvictionPolicy="LRU">

<persistence strategy="none"/><!-- In-memory Only Cache --><cacheEventListenerFactory

class="net.sf.ehcache.distribution.jms.JMSCacheReplicatorFactory"properties="replicateAsynchronously=false,

replicatePuts=false,replicateUpdates=true,replicateUpdatesViaCopy=false,replicateRemovals=true"propertySeparator=","/>

</defaultCache>

…キャッシュ追加処理の共有→しない

…キャッシュ更新処理の共有→する

…ただし、キャッシュ共有ではなく、削除のみ

…キャッシュ削除処理の共有→する

18/32

Page 19: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

セッション情報の共有

• StickySession機能を利用しない環境ではセッション情報の共有が必要

1. サーバーAにログオン2. サーバーAのセッションにユーザー01のログオン情報が書き込まれる

3. メニュー画面の表示のためサーバーBへアクセス4. ログオン情報がないためログオン画面が表示されてしまう

ロードバランサ

StickySession

ユーザー01

サーバーA

セッション情報ログオン

メニューへアクセス

サーバーB

セッション情報

ユーザー01はログオンしてます。

ユーザー01はログオンしていません。

19/32

Page 20: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

SpringSessionのセッション共有[1]• Redis(KVS)の利用(別途Redisサーバーが必要)• これまで:マルチセッション実現のためにRedisを利用• 今後:セッション情報の共有のためにもRedisを利用

• 複数台のWagbyアプリケーションで同じRedisに接続• Redisを通してセッション情報を共有

WagbyDesigner >環境 >サーバ

wagbyapp

wagbyapp

wagbyapp

Redis

セッション情報

20/32

Page 21: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

SpringSessionのセッション共有[2]• SpringSession+Redisでのセッション共有• セッションに格納するオブジェクトはjava.io.Serializableインタフェースを実装する

• Serializableを実装できないオブジェクトはtransient修飾子を付与しシリアライズ対象外とする• Wagbyでの主なシリアライズ対象外クラスは以下

※間接的にセッションに格納されていたためtransientとした• ApplicationContext(Springが提供するクラス)• LoginContext(JAAS認証で利用)

• ApplicationContextはリクエスト毎に再セットすることで解決

wagbyapp

Redis

セッション情報

シリアライズ

デシリアライズ

SpringSession21/32

Page 22: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

SpringSessionのセッション共有[3]• LoginContextのシリアライズ対応• javax.security.auth.loginパッケージに属するクラス• ログオン/ログオフ機能を持ち、権限情報を保持• 派生クラスでのSerializable実装は困難• 権限はjavax.security.auth.Subjectで表現(シリアライズ可能)• LoginContextはSubjectを引数とすることでもインスタンス作成が可能

• Subjectをセッションに格納し、必要に応じてLoginContextのインスタンスを復元することとした

new LoginContext(logonModuleName, subject)

22/32

Page 23: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

SpringSessionのセッション共有[4]• カスタマイズの際の注意点• CGLIBでProxy化されたクラスをセッションに格納するとデシリアライズ時にエラー• 厳密にはシリアライズ時と異なるサーバーでデシリアライズされた場合にエラーとなる

• 対策• セッションに格納しない。都度ApplicationContextから取得

• 特にDAOやEntityServiceはセッションに格納してはいけない• CGLIBではなくJDKDynamicProxyを使う

• 当該クラスにインターフェースを作成(JDKDynamicProxyはインタフェースが必須)

• bean定義で proxy-target-class=“false”属性を指定• アノテーションの場合は @XXX(proxyMode =ScopedProxyMode.TARGET_CLASS)

java.lang.ClassNotFoundException: jp.jasminesoft.wagby.XXX$$EnhancerBySpringCGLIB$$17546ee8

23/32

Page 24: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

Redisなしでの動作•以下の条件ではオートスケール環境でもRedisは不要となる• WagbyをREST APIサーバーとしてのみ利用する• すべてのアクセスは“X-Wagby-Authorization”を使ってステートレス接続とする• 1度のアクセスで「ログオン >目的の処理 >ログオフ」を行うので、Wagby側ではセッションで情報を維持する必要がない

• セッション情報の維持が不要のため複数サーバーでのセッション共有の必要がない (=Redisは不要)

24/32

Page 25: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

ロックについて

•悲観ロック• クラスタリング時の機能をそのまま利用• RDBのjfclockobjectテーブルにロック情報を格納し、各サーバー間で共有する

•楽観ロック• そもそも稼働サーバーの台数に依存しない機能

• 一台でも複数台でも同じ仕組みで動作する• データテーブルのバージョンカラムを使ってロックを管理

25/32

Page 26: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

ジョブスケジューラーの対応[1]• Quartz• Wagbyのジョブスケジュールを実現しているライブラリ• 指定した時刻にジョブを実行

•単一サーバーでの動作• スケジュール情報をメモリー上に保持(RAMJobstore)

•複数サーバーへの対応• スケジュール情報をRDBに保持 (JDBCJobstore)• 各サーバーで共通のスケジュール情報を参照• 指定した時刻に1つのジョブをいずれかのサーバーで実行する

26/32

Page 27: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

ジョブスケジューラーの対応[2]• QuartzJDBCJobstore• データベースに専用のテーブルを用意(11テーブル)• テーブル名の先頭にQRTZ_がついている

• QRTZ_LOCKS,QRTZ_TRIGGERS,QRTZ_JOB_DETAILS,QRTZ_CALENDARS,…

• Quartz内部でjob,triggers,calendarsと呼ばれる情報を格納する

• テーブルに対応するWagbyのモデルは存在しない• Wagbyが直接テーブルを操作することはせずQuartzに移譲• モデルが存在しないため、CREATE TABLE/DROP TABLE用のDDLは特別に管理している

• テーブルのCREATEやDROPはInitLoaderで実行• jfcjobscheduleモデルのテーブルの作成/削除時に同時実行

27/32

Page 28: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

ジョブスケジューラーの対応[3]• ジョブの実行制御• 実行対象:1インスタンス

• 各サーバ中1台のみが実行するジョブ• Exportジョブ、メール送信ジョブ等

• 実行対象:全インスタンス• 各サーバーで個々に実行するジョブ• メンテナンスモード切替用ジョブ

• 例:AM0:00にすべてのサーバーをメンテナンスモードにする• JDBCJobstoreは全インスタンスを実行対象とする仕組みがない• この問題解決のためJDBCJobstoreとRAM Jobstore併用する仕組みとした

• JDBCJobstore :1インスタンス実行用• RAMJobstore :全インスタンス実行用

28/32

Page 29: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

ジョブスケジューラーの対応[4]• jfcjobscheduleモデルの拡張• 実行対象項目の追加

• one(1インスタンス)、all(全インスタンス)を選択• 実行種別が未指定の場合は1インスタンス実行とする

• 更新日時項目の追加• ジョブスケジュールを変更した日時を格納

• ジョブスケジュール変更情報の共有• ActiveMQのPublish/Subscribeメッセージング機能を利用

• あるサーバーでジョブスケジュールの変更を行うと全サーバーへ通知され、各サーバーでジョブスケジュールの再読込を行う(RAMJobstoreのみ)

29/32

Page 30: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

ジョブスケジューラーの対応[5]1.ジョブスケジュールを修正

topic

ActiveMQ

Publisherジョブスケ

ジュールの変更

メッセージ

Sbscriber

Sbscriber

Sbscriber

メッセージ

メッセージ

メッセージ

Wagbyアプリケーション

Wagbyアプリケーション

Wagbyアプリケーション

Jfcjobscheduleテーブル

RDB2.jfcjobscheduleテーブルを更新

3.メッセージをtopicに登録

4.topicに購読登録している全Sbscriberにメッセージを送信

5.Jfcjobscheduleテーブルのデータを読み込み、RAMJobstoreスケジューラーを更新する

Wagbyアプリケーション

30/32

Page 31: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

ワークフローの対応

•同時承認への対応• 同一データに対する複数ユーザーの同時承認

• 単一サーバーでの動作時• 承認処理を行うメソッドにsyncronized修飾子を付与• 後から行われた承認処理は待ち状態となり、処理再開後の状態チェックで2重承認を回避する

• オートスケール時の動作• 承認対象のデータに悲観/楽観ロックを行い2重承認が行われた場合はロックエラーとする

• 現在も悲観ロック処理は行われているが、承認処理の 後のごく短い時間のみ

• ロックの範囲を承認処理全体とすることで対応

31/32

Page 32: Wagbyのオートスケールに 関する技術情報Redisなしでの動作 • 以下の条件ではオートスケール環境でもRedisは 不要となる • WagbyをREST APIサーバーとしてのみ利用する

まとめ

• オートスケール対応で内部処理を変更している。• ロック処理は変更なし。• キャッシュは ehcacheのメッセージを使って整合性をとる。MQが必要。• SpringSessionのセッション共有はRedisを使う。• ジョブスケジューラは quartzの制御方式を使う。• ワークフローは承認処理でロックを適用する。

•必要なミドルウェア• MQは必須。今後、MQを活用する局面は増える見込み。• Redisは任意。(p.24の条件が整えば、なくても動作する)

32/32