WARデプロイと並行デプロイで無停止に切り替える
目標
WARデプロイの実際の動作を確認し、並行デプロイ(Parallel Deployment)でセッションを切らずにバージョンを上げたうえで、検証までを行うデプロイスクリプトを作成できるようになります。
なぜ重要なのか
単一WAS環境で無停止デプロイを行うには、L4の前段でサーバーを外したり入れたりする必要があると、考えがちです。ところが、Tomcatにはもともと並行デプロイの機能があります。ファイル名に##버전(韓国語の語は「バージョン」を意味します)を付けると、同じコンテキストに複数のバージョンが共存し、既存のセッションは旧バージョンへ、新規リクエストは新バージョンへ行きます。多くのSI現場が、この機能を知らないまま、明け方の停止デプロイを繰り返しています。もう1つ、デプロイスクリプトが展開の完了を待たないと、失敗したデプロイを成功と報告します。それは、停止デプロイよりはるかに悪いです。
ステップ
- Tomcatを起動して、
/opt/lab/samples/labhub-1.0.0.warを/opt/tomcat/webapps/labhub##001.warにデプロイします。http://127.0.0.1:8080/labhub/versionが1.0.0を返す必要があり、catalina.outにlabhub##001のデプロイ記録が残る必要があります。(このデプロイ記録が、以降のステップの証拠として使われます。) - 展開されたディレクトリを確認して、
/root/tc/explode.csvを作成します。1行目はpath,existsです。次の4つのパスについて、Y/Nを書きます。WEB-INF/web.xml、WEB-INF/classes、WEB-INF/lib、META-INF /opt/lab/samples/labhub-2.0.0.warを/opt/tomcat/webapps/labhub##002.warにデプロイします。このとき、##001を先に削除せず、2つのバージョンが共存するようにしてください。http://127.0.0.1:8080/labhub/versionが、今度は2.0.0を返す必要があり、catalina.outにlabhub##001とlabhub##002の両方のデプロイ記録がある必要があります。/root/tc/parallel.mdを作成します。次の3つが本文に入っている必要があります。- 既存のセッションを持つリクエストが、どのバージョンに行くか
- 新規リクエストが、どのバージョンに行くか
- バージョン文字列が文字列の比較で並べられるため、
##1/##10のような表記が危険な理由001と002の2つの文字列が、両方とも登場する必要があります。
##001バージョンを完全に削除します(WARと展開ディレクトリの両方)。削除後も、http://127.0.0.1:8080/labhub/versionが2.0.0である必要があります。/opt/lab/samples/labhub-boot.jarをポート8082でバックグラウンドで起動し、ログを/root/tc/boot.logに残します。http://127.0.0.1:8082/versionが200である必要があります。/root/tc/war-vs-jar.csvを作成します。1行目は항목,WAR,JAR(韓国語の語は「項目」を意味します)です。배포단위、톰캣버전관리、포트지정、롤백、무중단の5項目(韓国語の語は、順に「デプロイ単位」「Tomcatバージョン管理」「ポート指定」「ロールバック」「無停止」を意味します)が必要で、各セルは空であってはいけません。/root/tc/deploy-war.shを作成します。引数を2つ(WAR파일 컨텍스트명、韓国語の語は、順に「WARファイル」「コンテキスト名」を意味します)受け取って、- WARファイルがないか、サイズが0なら、すぐに0以外の終了コードで終わります。
- あれば
webappsに配置して、最大30秒間ポーリングしながら、展開を待ちます。 http://127.0.0.1:8080/<컨텍스트명>/version(韓国語の語は「コンテキスト名」を意味します)が200なら終了コード0、30秒以内にならなければ、0以外の終了コードで終わります。
参考
curl -s -o /dev/null -w '%{http_code}' <URL>で、ステータスコードだけを取得します。- WARはzipです:
unzip -l 파일.war(プレースホルダーはファイル名です)で、内容を見られます。 - 実行可能JARのポート指定:
java -jar app.jar --server.port=8082 - よくあるミス1: コピー直後にすぐ検証して、404を失敗と判定するミスです。ポーリングが必要です。
- よくあるミス2:
##002をデプロイするときに、##001のWARを先に削除するミスです。そうすると、並行デプロイではなく、ただの置き換えデプロイです。 - よくあるミス3: デプロイスクリプトが、検証なしで常に0で終わるミスです。失敗したデプロイを成功と報告するスクリプトが、最も危険です。
最初のバージョンのデプロイ
Tomcatを起動して、/opt/lab/samples/labhub-1.0.0.warを/opt/tomcat/webapps/labhub##001.warにデプロイします。http://127.0.0.1:8080/labhub/versionが1.0.0を返す必要があり、catalina.outにlabhub##001のデプロイ記録が残る必要があります。(このデプロイ記録が、以降のステップの証拠として使われます。)
ファイル名に##バージョンを付けると、コンテキストパスは##の前の部分になります。展開は非同期なので、コピー直後にすぐリクエストすると、404になることがあります。
展開結果の確認
展開されたディレクトリを確認して、/root/tc/explode.csvを作成します。1行目はpath,existsです。次の4つのパスについて、Y/Nを書きます。WEB-INF/web.xml、WEB-INF/classes、WEB-INF/lib、META-INF
WARはzipです。展開されたディレクトリで、標準的なWebアプリケーションの構造を探してみてください。何が必須で、何が任意かが、このステップの学習ポイントです。
2つ目のバージョンの並行デプロイ
/opt/lab/samples/labhub-2.0.0.warを/opt/tomcat/webapps/labhub##002.warにデプロイします。このとき、##001を先に削除せず、2つのバージョンが共存するようにしてください。http://127.0.0.1:8080/labhub/versionが、今度は2.0.0を返す必要があり、catalina.outにlabhub##001とlabhub##002の両方のデプロイ記録がある必要があります。
同じコンテキスト名に、より高いバージョン文字列を付けてデプロイします。2つのWARが同時に展開された状態である必要があり、新しいリクエストは、高いバージョンに行く必要があります。
セッションドレイニングの理解の整理
/root/tc/parallel.mdを作成します。次の3つが本文に入っている必要があります。
- 既存のセッションを持つリクエストが、どのバージョンに行くか
- 新規リクエストが、どのバージョンに行くか
- バージョン文字列が文字列の比較で並べられるため、
##1/##10のような表記が危険な理由001と002の2つの文字列が、両方とも登場する必要があります。
並行デプロイで、既存のセッションと新規セッションが、それぞれどこに行くかを、文章で整理します。バージョン文字列が文字列の比較で並べられる点も、一緒に書いておいてください。
旧バージョンを停止する
##001バージョンを完全に削除します(WARと展開ディレクトリの両方)。削除後も、http://127.0.0.1:8080/labhub/versionが2.0.0である必要があります。
旧バージョンのWARと展開ディレクトリを、一緒に削除する必要があります。削除後もサービスが途切れてはならず、バージョンの応答は、そのまま新しいバージョンである必要があります。
実行可能JARの起動
/opt/lab/samples/labhub-boot.jarをポート8082でバックグラウンドで起動し、ログを/root/tc/boot.logに残します。http://127.0.0.1:8082/versionが200である必要があります。
組み込みTomcatの方式は、ポートを実行引数で与えます。バックグラウンドで起動して、ログはファイルに残してください。
WARとJARの比較表
/root/tc/war-vs-jar.csvを作成します。1行目は항목,WAR,JAR(韓国語の語は「項目」を意味します)です。배포단위、톰캣버전관리、포트지정、롤백、무중단の5項目(韓国語の語は、順に「デプロイ単位」「Tomcatバージョン管理」「ポート指定」「ロールバック」「無停止」を意味します)が必要で、各セルは空であってはいけません。
技術的な優劣ではなく、「運用手順がどちら側に標準化されているか」が、実際の選択を左右するという観点で、整理してみてください。
デプロイスクリプトの作成
/root/tc/deploy-war.shを作成します。引数を2つ(WAR파일 컨텍스트명、韓国語の語は、順に「WARファイル」「コンテキスト名」を意味します)受け取って、
- WARファイルがないか、サイズが0なら、すぐに0以外の終了コードで終わります。
- あれば
webappsに配置して、最大30秒間ポーリングしながら、展開を待ちます。 http://127.0.0.1:8080/<컨텍스트명>/version(韓国語の語は「コンテキスト名」を意味します)が200なら終了コード0、30秒以内にならなければ、0以外の終了コードで終わります。
失敗したデプロイを成功と報告するスクリプトが、最も危険です。展開を待つポーリングループと、検証失敗時の0以外の終了コードが核心です。