8 エディションベースの再定義(EBR)を使用した本番環境でのアプリケーションの更新

EBRは、データベース機能の1つであり、アプリケーションのデータベース・コンポーネントをオンラインで更新する柔軟性を備えているため、更新がアプリケーションの可用性に影響を及ぼすことがなくなるのですが、この機能について学習します。

この章には次の項が含まれます:

エディションベースの再定義について

EBRを使用すると、アプリケーションは、同じデータベース内に2つのエディションのデータベース・スキーマを同時に格納できるようになります。1つはアップグレード前のアプリケーションで、もう1つはアップグレード後のアプリケーションで使用されるものです。

オンライン更新が完了すると、アップグレード前のアプリケーションは以前のエディションのデータベース・スキーマ(エディション1)を参照し、アップグレード後のアプリケーションは新しいエディションのデータベース・スキーマ(エディション2)を参照します。

このように複数のエディションのデータベースが共存することで、進行中のユーザー・セッションはアップグレード前のアプリケーションを引き続き使用でき、新しいセッションはアップグレード後のアプリケーションに誘導されます。既存のセッションがすべて完了すると、アップグレード前のアプリケーションはリタイアし、アップグレード後のアプリケーションが完全に稼働した状態となり、アップグレード・プロセス全体が停止時間なしで完了します。

EBRの詳細およびこの機能に関連する主要な用語の確認には、『Database開発ガイド』エディションベースの再定義の使用に関する項を参照してください。

ノート:

EBRをWebLogicのダウンタイムなしのパッチ適用(ZDTパッチ適用)機能とともに使用して、アプリケーションを更新することも可能です。ただし、アプリケーションでEBRを有効化し、ドメイン全体にダウンタイムなしで更新がロールアウトされる際に、構成の更新を同期する必要があります。詳細は、次の各項を参照してください。

アプリケーションでのEBRの有効化

環境でEBRを有効化する前に、WebLogic Serverドメインを停止する必要があります。

『Oracle WebLogic Serverサーバーの起動と停止の管理』「サーバーの起動と停止」を参照してください。

EBRを使用するには、次に示す重要なステップを実行する必要があります:

  • ユーザーおよびスキーマ・オブジェクトがエディションを使用できるようにする
  • アプリケーションがエディショニング・ビューを使用できるようにする

EBRに対するアプリケーションの準備の詳細は、『Database開発ガイド』「アプリケーションをアップグレードするためのEBRの使用」を参照してください。

エディションを使用するためのWebLogicデータ・ソースの構成

EBRでの更新中、WebLogic Serverでは、既存のユーザー・セッションがアップグレード前のアプリケーションに接続された状態が保たれ(参照されるのはデータベース・スキーマのエディション1)、新しいユーザー・セッションはアップグレード後のアプリケーションに接続されるよう(参照されるのはデータベース・スキーマのエディション2)、ユーザー・セッションが自動的に管理されます。

ユーザー・セッションの自動管理を行いやすくするには、WebLogicデータ・ソースが接続するデータベース・エディションを判断できるよう構成する必要があります。データ・ソースは様々な方法で構成可能です。詳細は、『Oracle WebLogic Server JDBCデータ・ソースの管理』「エディションベースの再定義の使用」のエディションを使用するためのWebLogicデータ・ソースの構成に関する項を参照してください。

アプリケーション・ソフトウェアおよびドメイン構成の更新について

通常、アプリケーションの更新は、ソフトウェア(コード)の更新とWebLogic Serverのドメイン構成データの更新という2つのステップで行われます。ご使用の環境に応じ、ステップごとに異なる更新メカニズムを使用します。

たとえば、ソフトウェアは新しい製品バイナリのインストールによって更新されますが、構成データは管理サーバーを介して更新されます。構成の変更は、まずWLST、管理REST API、JMXなどのツールを介して管理サーバーに伝達されます。その後、管理サーバーは、ドメイン内の管理対象サーバーに変更をロールアウトします。

EBRを使用するアプリケーションのローリング更新を実行する際、ソフトウェアを更新するために構成も同時に更新する必要がある場合、更新メカニズムが異なると、ソフトウェア・バージョンとドメイン構成のバージョンが一致しなくなり(古いバージョンのソフトウェアで新しい構成データが使用される、または新しいバージョンのソフトウェアで古い構成データが使用される)、矛盾した状態になる可能性があります。

例8-1に、ソフトウェアとドメイン構成のバージョンが矛盾した状態を示します

次のような環境があるとします:

  • 管理サーバー1台 - AS。
  • 管理対象サーバー2台 - MS1およびMS2。
  • サーバーで使用されているソフトウェアはS1で、データベース・エディションE1 (アップグレード前の状態)に接続されています。
  • アップグレード後、サーバーで使用するソフトウェアは新しいS2になり、新しいデータベース・エディションE2に接続した状態になっている必要があります。

管理サーバーはドメイン内で最初に更新されるサーバーであり、構成の変更の後に、更新されたソフトウェアS2のインストールを受け取ります。2台の管理対象サーバー(MS1とMS2)は、引き続きアップグレード前の状態(S1-E1の組合せ)です。その後、管理サーバーは構成の変更をMS1とMS2にブロードキャストします。サーバーは、古いソフトウェア(S1)を引き続き使用しながら、更新された構成データを受け取り、データベースの新しいエディション(E2)に接続します。

この時点で、サーバーに存在するのは、新しい構成データで構成された古いソフトウェアです(S1-E2の組合せ)。この矛盾した状態は、管理対象サーバーのローリング再起動を実行することで、アプリケーションをアップグレードし、MS1とMS2の両方でソフトウェアがS2に更新されるまで続きます。これで、サーバーは、ソフトウェアも構成データも更新されたバージョンを使用する矛盾のない状態(S2-E2の組合せ)になります。

バージョン間に矛盾がある状態は、先にソフトウェアを更新してから構成データを更新した場合にも発生します。この場合、管理サーバーは新しいソフトウェアS2で更新され、管理対象サーバーのローリング再起動を実行すると、MS1とMS2の両方でソフトウェアがS2に更新されます。この時点で、サーバーは、古い構成データで構成された新しいソフトウェアを使用しています(S2-E1の組合せ)。その後、管理サーバーは構成の更新を受け取り、管理対象サーバーにブロードキャストします。これで、サーバーは、新しい構成データで構成された新しいソフトウェアを使用する矛盾のない状態(S2-E2の組合せ)になります。

(ソフトウェアが先か、構成が先かという)更新の順序に関係なく、矛盾の問題は発生します。EBRを使用してアプリケーションを更新する場合、ソフトウェア・バージョンと構成データのバージョンの不一致は望ましいものではありません。

調整と同期化を行ったローリング更新を実行すれば、ソフトウェアと構成データの間のこうした一時的な不一致を回避できます。

同期ローリング更新

同期ローリング更新中には、サーバーが新しいソフトウェア・バージョンで更新されるのと同時に構成データも更新され、構成とサーバー上のソフトウェア・バージョンが完全に同期されます。

例8-2 同期ローリング更新

管理サーバー上でソフトウェアと構成を更新したとします(S2-E2)。管理対象サーバーはアップグレード前の状態のままで、使用しているのは以前のエディション(E1)と通信している古いソフトウェア(S1)です。ソフトウェアは古いままですが、新しい構成(つまり、新しいエディションであるE2)に対する準備はできていません。

管理サーバーでは管理対象サーバーの準備ができているかどうかを認識しないため、構成の変更を受け取ったら、その変更を管理対象サーバーに渡す必要があると判断します。ただし、管理対象サーバーが同期をサポートするように構成されている場合は、準備ができるまで変更は無視されます。たとえば、MS1で同期ローリング再起動を実行し、新しいソフトウェアで再起動すると、MS1の同期ロジックにより、無視した変更を受け入れる準備ができたことが示されます。これは、MS1のソフトウェアが(S1からS2に)更新され、データベース・スキーマの新しいエディション(E2)を使用して更新されたソフトウェア(S2)と通信することを意味します。

この時点では、2つのエディションのデータベースが実行されており、MS1とMS2の個々のサーバーは、一度に1つのエディションに対して構成されるため、それぞれ別のエディションに接続されています。MS1は新しいバージョンのソフトウェア(S2)を実行し、新しいエディションのデータベース(E2)を使用しています。MS2は古いバージョンのソフトウェア(S1)を実行し、古いエディションのデータベース(E1)を使用しています。管理対象サーバー同士の構成(MS1 – E2とMS2 – E1)は一致していませんが、それぞれはソフトウェアとデータベース・スキーマのバージョンに矛盾がない状態(MS1はS2-E2、MS2はS1-E1)です。このプロセスは同期ローリング更新と呼ばれ、ソフトウェアのバージョンがWebLogic構成のバージョンと同期された状態が保たれるため、データベース・エディションの同期も維持されます。

同様に、MS2のソフトウェアが新しいバージョンになると、MS2も準備が整い、新しい構成が受け入れられます。プロセスが完了すると、すべてのサーバーのソフトウェアが新しいバージョン(S2)になり、新しいデータベース・エディション(E2)を指すようになります。

WebLogic Serverには、調整および同期化されたローリング更新を実行するためのメカニズムが組み込まれており、これを使用すれば、ソフトウェア更新が完了した後にのみ、管理対象サーバーがドメイン構成の更新を受け入れることを保証できます。つまり、管理対象サーバーでは、更新されたソフトウェアがサーバーにインストールされた後にのみ、構成の変更が処理されます。これらのメカニズムにより、ソフトウェアと構成データのバージョンの矛盾が防止され、構成バージョンとソフトウェア・バージョンの同期が常に保たれます。

アプリケーション・ソフトウェアおよびドメイン構成の更新の同期

WebLogic Serverは、管理対象サーバーで構成の変更を受け入れるかどうかを判断するのに役立ちます。

管理対象サーバーの更新方法に応じて、次の2つのチェッカのいずれかを使用できます:

  • ロックファイル・チェッカ
  • バージョン・チェッカ

これらのチェッカは、管理対象サーバーが、インストールされているソフトウェアと同期していない構成の変更を受け入れるのを防止します。これらのチェッカは、開始されるタイミングに応じて、次のように分類されます:

  • 構成独立型(例: ロックファイル・チェッカ): 環境が変更されると、チェッカが開始されます(構成の変更にかぎりません)。チェッカは、変更の性質に応じて、変更を無視するか受け入れるかを管理対象サーバーに指示します。
  • 構成ベース型(例: バージョン・チェッカ): 構成を更新するとチェッカが開始されます。チェッカは、変更内容に応じて、変更を受け入れるか拒否するかを管理対象サーバーに指示します。

チェッカは、次のイベント中に、管理対象サーバーが管理サーバーから変更の可能性を示す通知を受信すると開始されます:

  • 管理サーバーが構成の変更を受け入れて、管理対象サーバーに渡したとき。
  • 管理対象サーバーを再起動し、管理対象サーバーが管理サーバーからの更新を検出したとき。
  • 管理対象サーバーが、変更を示す定期的なシグナルを管理サーバーから受信したとき。

これらのチェッカに加え、WebLogic Serverでは独自のJavaコード・プラグインの記述も可能です。「独自のJavaプラグインの記述と構成」を参照してください。

ロックファイル・チェッカ

構成独立型のロックファイル・チェッカは、管理対象サーバーが管理サーバーからの構成の変更を検出すると開始されます。ロックファイルを管理対象サーバーが実行されているマシンに設定します。ロックファイルが存在するかぎり、管理対象サーバーは管理サーバーからの構成の変更を受け入れません。管理対象サーバーでソフトウェアが更新されたら、ロックファイルを削除します。ロックファイルが削除されるとすぐに、構成の変更が受け入れられ、管理対象サーバーによって適用されます。

バージョン・チェッカ

一方、構成ベースのバージョン・チェッカは、管理対象サーバーが構成の更新を受信すると開始されます。このチェッカを使用すると、管理対象サーバーが、構成データの変更を受け入れるソフトウェアのバージョンを判断できるようになります。これを可能にするには、ソフトウェアのインストール・プロセスの一環として、ソフトウェアのバージョンが記載されたファイルを含める必要があります。

管理対象サーバーが、管理サーバーから構成の更新を受信すると、バージョン・チェッカの一部であるバージョン(数値)をインストール・ファイルに含まれているソフトウェア・バージョンと比較し、2つのバージョンが一致する場合にのみ変更を受け入れます。

ロックファイル・チェッカの構成

管理対象サーバーが管理サーバーからの構成の変更を検出すると、ロックファイル・チェッカが呼び出されます。このチェッカを使用するには、予想される変更フック・ポイントでこのチェッカを構成する必要があります。

ノート:

環境を構成する管理サーバーと管理対象サーバーが、別々のマシンで実行されていることを前提としています。そのため、各サーバーには、それぞれにconfig.xmlファイルのコピーがあります。
  1. WLSTを使用して管理サーバーに接続します:
    connect('<username>', 'ok', 't3://localhost:7001')
  2. 次に示すように、ロックファイル・チェッカを参照するコールアウトを作成します:
    edit()
    startEdit()
    cd('/')
    callout1=cmo.createCallout('LockFileChecker-1')
    callout1.setHookPoint("HOOK_POINT_EXPECTED_CHANGE")
    callout1.setClassName("weblogic.configuration.ConfigurationLockfileChecker")
    callout1.setArgument("<Location of the Lock File in the Managed Server>")
    activate()

例8-3では、ロックファイル・チェッカの使用について説明します

  1. 上のステップ1の説明に従い、WLSTを使用して管理サーバーに接続します。
  2. 管理サーバー・ノードにコールアウトを作成してアクティブ化し、コールアウトの変更を管理対象サーバーにプッシュします。
  3. 管理対象サーバーが実行されているマシン(ロックファイル・チェッカの構成時にコールアウトの引数として指定した場所)にLockfileという名前のファイルを作成します。これで、管理対象サーバーは、管理サーバーからの構成の変更を受け入れなくなります。
  4. WebLogic Server管理コンソールにログインし、「環境」を開き、「サーバー」をクリックします。
  5. 構成を変更する管理対象サーバーを選択します。
  6. 「構成」 > 「同時実行性」ページに移動し、「最大同時新規スレッド」の値を50から100に変更します。
  7. 変更を保存してアクティブ化します。
  8. 管理対象サーバーのconfig.xmlファイルを確認するか、WLSTを使用して管理対象サーバーに接続し、「最大同時新規スレッド」の値を確認します。

    ロックファイルが存在するため、管理対象サーバーの値は更新されていません。

  9. ここで、管理対象サーバーからロックファイルを削除し、管理対象サーバーのconfig.xmlファイルを確認するか、WLSTを使用して管理対象サーバーに接続します。

    「最大同時新規スレッド」の値を確認します。値が100に更新されています。

バージョン・チェッカの構成

バージョン・チェッカは、管理対象サーバーが管理サーバーから構成の更新を受信すると呼び出されます。このチェッカを使用するには、受信した変更フック・ポイントでこのチェッカを構成する必要があります。

ノート:

環境を構成する管理サーバーと管理対象サーバーが、別々のマシンで実行されていることを前提としています。そのため、各サーバーには、それぞれにconfig.xmlファイルのコピーがあります。
  1. WLSTを使用して管理サーバーに接続します:
    connect('<username>', '<password>', 't3://localhost:7001')
  2. ドメインにインストールされているソフトウェアのバージョンを1.1に変更するとします:
    edit()
    startEdit()
    cd('/')
    cmo.setInstalledSoftwareVersion('1.1')
    activate()
  3. 次に示すように、バージョン・チェッカを参照するコールアウトを作成します:
    edit()
    startEdit()
    cd('/')
    callout1=cmo.createCallout('VersionChecker-1')
    callout1.setHookPoint("HOOK_POINT_CHANGE_RECEIVED")
    callout1.setClassName("weblogic.configuration.ConfigurationVersionChecker")
    callout1.setArgument("<Location of the Version File on the Managed Server>")
    activate()

例8-4では、バージョン・チェッカの使用について説明します

  1. 上のステップ1の説明に従い、WLSTを使用して管理サーバーに接続します。
  2. 管理サーバー・ノードにコールアウトを作成してアクティブ化し、コールアウトの変更を管理対象サーバーにプッシュします。
  3. バージョン・チェッカ・ファイル(/MyInstallation/Servers/MS1/VersionCheckerなど、バージョン・チェッカの構成時にコールアウトの引数として指定した場所)を、管理対象サーバーが実行されているマシンに作成します。ファイルにはバージョン番号が記載されている必要があります。
    echo "1.0"  >  </MyInstallation/Servers/MS1/VersionChecker >
  4. WebLogic Server管理コンソールにログインし、「環境」を開き、「サーバー」をクリックします。
  5. 構成を変更する管理対象サーバーを選択します。
  6. 「構成」 > 「Webサービス」 > 「バッファリング」ページに移動し、retry-countの値を999に変更します。
  7. 変更を保存してアクティブ化します。
  8. 管理対象サーバーのconfig.xmlファイルを確認するか、WLSTを使用して管理対象サーバーに接続し、retry-countの値を確認します。

    値は999に更新されていません。これは、バージョン・チェッカ・ファイルに指定されているインストール済ソフトウェア(1.1)のバージョンが、コールアウト(1.0)に設定されている予期されるバージョンと一致しないために起こります。

  9. コールアウトに構成されているバージョンと同じバージョンになるように、バージョン・チェッカ・ファイルのバージョン番号を変更します。ここで、バージョン・チェッカ・ファイルのバージョンを更新する前に、インストールされたソフトウェアが更新されます。
    echo "1.1" >  <Location of the Version Checker>
  10. 管理対象サーバーのconfig.xmlファイルを確認するか、WLSTを使用して管理対象サーバーに接続します。

    2つのバージョンが一致したため、retry-countの値が999に更新されたことを確認します。

独自のJavaプラグインの記述と構成

WebLogic Serverには、ロックファイル・チェッカとバージョン・チェッカだけでなく、構成を受け入れるか拒否するかを決定する独自のカスタム・ロジックを記述する柔軟性もあります。実際、ロックファイル・チェッカとバージョン・チェッカはどちらも、Javaプラグインです。

Javaプラグインには、Expected ChangeChange Receivedの2つのタイプがあります。Change Receivedプラグインでは構成の変更を確認し、受け入れるか拒否するかを判断できるのに対し、Expected Changeプラグインではそれをできない点が異なります。ただし、前者は、WebLogicの部分でもプラグインの部分でも計算が少なくてすみます。

プラグインを実装するには、weblogic.callout.spi.WebLogicCallout.javainitおよびcalloutメソッドをオーバーライドする必要があります。

プラグインをインストールするには、次のようにします:
  1. Javaプラグイン・クラスを管理対象サーバーのクラスパスに追加し、サーバーを再起動します。
  2. すぐに使用できるチェッカの説明にあるように、WLSTを使用してコールアウトを作成します。「ロックファイル・チェッカの構成」および「バージョン・チェッカの構成」を参照してください。

ConfigurationLockfileCheckerはExpected Changeプラグインです。次のコードでは、WebLogic DomainMBeanにアクセスしません。実行されているマシン(つまり、インストールされている管理対象サーバー)の状態に基づいて判断し、構成済のファイルがあるかどうかを確認するだけです。

package weblogic.configuration;

import java.io.File;
import java.util.Map;
import weblogic.callout.spi.WebLogicCallout;
/*
 This is provided out of box for the usage of orchestrating configuration updates and rollout.
 To use this, user will need to create a Callout under domain,  with the following parameter

     name:        callout-0
     hookpoint:   HOOK_POINT_EXPECTED_CHANGE
     classname:   weblogic.configuration.ConfigurationLockfileChecker
     argument:    /wls-installation/servers/Server-0/CONFIGURATION_LOCKFILE

     both hookpoint and classname should be as above,  argument is the path to the configuration lockfile.  You can name
     it any way you want.
     This class will be invoked whenever the following occurs:
      #1. managed server boots up,
      #2. managed server does periodic 'heartbeat' for getting any changes from the admin server
      #3. admin server commit a configuration transaction and send the bits to this managed server

      The existence of this lockfile is checked.  If the lockfile exists, the managed server configuration will be updated,
      otherwise, the change will be ignored until the next time, one of the above 3 situation occurs.

 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
 */
public class ConfigurationLockfileChecker implements WebLogicCallout {

  File lockfile = null;

  @Override
  public String callout(String hookPoint, String location, Map<String, Object> values) {


    if (WebLogicCallout.HOOK_POINT_EXPECTED_CHANGE.equals(hookPoint)) {
      if (lockfile != null && lockfile.exists()) {
        return WebLogicCallout.RESPONSE_IGNORE;
      }
      return WebLogicCallout.RESPONSE_ACCEPT;
    }

    return WebLogicCallout.RESPONSE_CONTINUE;
  }

  public void init(String argument) {
    if (argument != null) {
      lockfile = new File(argument);
    }
  }
}

ConfigurationVersionCheckerはChange Receivedプラグインです。次のコードでは、ローカル・マシンとWebLogic DomainMBeanの両方を確認して判断を行います。(WebLogic DomainMBean内の)構成済のバージョンが、管理対象サーバーにインストールされているソフトウェアのバージョンと一致するかどうかを確認します。

package weblogic.configuration;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Map;
import weblogic.callout.spi.WebLogicCallout;
import weblogic.management.configuration.DomainMBean;

/**
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
 */

/*
     This is provided out of box for the usage of orchestrating configuration updates and rollout.
     To use this, user will need to create a Callout under the domain,  with the following parameter
       name:        callout-0
       hookpoint:   HOOK_POINT_CHANGE_RECEIVED
       classname:   weblogic.configuration.ConfigurationVersionChecker
       argument:    /wls-installation/servers/Server-0/CONFIGURATION_VERSION_CHECKER

     both hookpoint and classname should be as above,  argument is the path to the configuration version checker file.
     You can name it any way you want.

     You will also need to set the domain's <installed-software-version> for using this callout.

     This class will be invoked whenever the following occurs:
      #1. managed server boots up,
      #2. managed server does periodic 'heartbeat' for getting any changes from the admin server
      #3. admin server commit a configuration transaction and send the bits to this managed server

      If this configuration version checker exists, the content of this file,  which should be a version nmuber  eg, "1.0"
      will be used to compare with the domain's <installed-software-version>  property, eg "1.1".  If it matches, managed server's
      configuration will be updated,  otherwise, the change will be ignored until the next time, one of the above 3 situation
      occurs.
 */

public class ConfigurationVersionChecker implements WebLogicCallout {

  File versionFile = null;

  @Override
  public String callout(String hookPoint, String location, Map<String, Object> values) {
    if (WebLogicCallout.HOOK_POINT_CHANGE_RECEIVED.equals(hookPoint)) {
      String versionFromFile = getVersionFromFile();
      String pendingVersion = getVersionFromDomainMBean(values.get(WebLogicCallout.VALUES_PENDING));
      if (versionFromFile != null && pendingVersion != null){
        return versionFromFile.equals(pendingVersion) ? WebLogicCallout.RESPONSE_ACCEPT: WebLogicCallout.RESPONSE_IGNORE;
      }
    }
    return WebLogicCallout.RESPONSE_CONTINUE;
  }

  @Override
  public void init(String argument) {
    if (argument != null){
      versionFile = new File(argument);
    }
  }

  String getVersionFromFile() {
    if (versionFile != null && versionFile.exists()) {
      try (FileReader fileReader = new FileReader(versionFile)) {
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        StringBuffer stringBuffer = new StringBuffer();
        String readLine;
        while( (readLine = bufferedReader.readLine()) != null) {
          stringBuffer.append(readLine);
        }
        return stringBuffer.toString();
      } catch (FileNotFoundException e) {
      } catch (IOException e) {
      }
    }
    return null;
  }

  String getVersionFromDomainMBean(Object domainMBean) {
    if (domainMBean != null && domainMBean instanceof DomainMBean) {
      return ((DomainMBean)domainMBean).getInstalledSoftwareVersion();
    }
    return null;
  }
}