多くの組織では、独立した開発、ステージング、および本番環境を個別に使用して各組織の Web サイトの品質を維持しています。 これらの環境は、ArcGIS Enterprise 組織で使用される場合、一般的に以下に記載のとおり設定されます。
- 開発 - 開発環境に影響を及ぼさずに、アプリケーションやサービスをテストできるサンドボックス環境です。 通常、開発環境は、ArcGIS Enterprise の本番環境から切断された小規模なコンピューター上で実行されます。 変更は、開発環境で検証された後でステージング サイトに適用されます。
- ステージング - この環境は、本番環境のクローンまたはその他の近似環境です。 ステージング環境は、付加価値アプリケーションとマップ キャッシュの構築およびテスト、他のサードパーティ ソフトウェアのユーザー受け入れ/パフォーマンス/読み込みテストの実施、新しい商用データの更新のステージング、およびトレーニング アクティビティの実施に使用されます。 このレベルでのテスト結果に基づいて、変更を本番サイトに適用するか、変更を却下して開発環境から新規に処理が繰り返されるのを待機するかを決定します。 ステージング サイトは開発目的では使用しません。パフォーマンスと機能性のテストにだけ使用します。 Esri では、ArcGIS Enterprise 用のステージング ライセンスを、本番ライセンスよりも低いコストで提供しています。
- 本番 - GIS ユーザー (場合によっては一般ユーザー) がアクセスするわけですから、この環境では、開発またはテストは一切行われません。 本番サイトには、ステージング サイトでの綿密なテストを通過した変更だけが適用されます。
開発、ステージング、および本番の各環境では、それぞれ異なるデータベースとインフラストラクチャを使用することが理想的です。 これらの環境間で変更をテストして承認する方法については、組織ごとに独自のルールが設定されます。
環境間で変更を移動する際には、ロジスティックに関する課題が存在する場合があります。 このヘルプ トピックでは、パターンとスクリプトを使用して、ArcGIS Server サイトがポータルとフェデレートされている場合とスタンドアロンで使用されている場合のプロセス全体を紹介しています。
注意:
このトピックでは、開発、ステージング、および本番環境の ArcGIS Server に関する検討事項について説明します。 他の ArcGIS Enterprise コンポーネントについては取り上げません。
各環境の構成
各環境では、ArcGIS Server のインストール、サイトの作成、セキュリティの構成、SOE (サーバー オブジェクト エクステンション) の構成、およびその他の設定を行います。 これらのタスクのほとんどは手動で実行するほうが簡単ですが、スクリプトを使用して自動化することもできます。
まず、開発サイトを稼働できるようにしてから、ステージング サイトを作成し、その後に本番サイトを作成します。
サービスの配置
サービスを複数の環境に配置する際に重要となるのは、フォルダーとデータベースを ArcGIS Server に正しく登録し、SD (サービス定義) を使用して公開を行うことです。
ArcGIS Server へのフォルダーとデータベースの登録
フォルダーまたはデータベースを ArcGIS Server に登録するときは、データに対する公開者のパスとサーバーのパスの両方を指定します。
- 公開者のパスは、SD ファイルの作成に使用するコンピューター上でのデータ パスです。 アイテムを開発サーバー、ステージング サーバー、および本番サーバーのいずれに登録する場合でも、公開者のパスは常に同じです。
- サーバーのパスは、サーバー上でのデータ パスです。 このパスは、アイテムの登録先 (開発サーバー、ステージング サーバー、および本番サーバー) によって異なる場合があります。
登録するデータ フォルダーまたはデータベースが多数ある場合は、スクリプトを使用することもできます。 「例: テキスト ファイルにリストされたフォルダーとデータベースの登録」では、ArcPy の AddDataStoreItem 関数を使用して、テキスト ファイルに指定したフォルダーおよびデータベース接続のリストを登録しています。 テキスト ファイルは各環境に合わせて変更します。
サービスの公開
サービスを複数の環境に配置する場合は、SD ファイルを使用します。 SD を使用すると、サービスの公開に必要な情報を取得して、これらを 1 つの使いやすいファイルにパッケージ化できます。 SD 内に GIS データをパッケージ化することもできますが、各環境にあらかじめデータを読み込み、レプリケーションを使用してデータを同期するほうが簡単です。
いずれのサーバーでの公開にも柔軟に使用できるように、接続に依存しない SD ファイルを作成します ([サービス定義の保存] ウィザードで [利用可能な接続がありません] オプションを選択します)。 SD ファイルを公開するときに、ArcGIS Server は指定されたサーバー パスを使用するように、SD に記述されているパスを自動的に修正します。 慎重にデータ登録を行うことで、同じ SD ファイルを複数の環境に配置できます。
サービスの公開は、スクリプトの利用に適したタスクです。 ArcPy のサービス定義のアップロード関数を使用して各 SD を公開するスクリプトを作成することができます。
SD からサービスを配置した後、サービスで必要なエクステンションを有効にします。 これは手動で、またはスクリプトを使用して実行できます。
テキスト ファイルにリストされている各種サービスに権限を適用する作業もスクリプト化できます。
サービスの更新
新しいプロパティを使用したり、ソース ドキュメントの変更を反映したりするために、サービスの更新が必要となる場合があります。 このような場合は、複数の環境でサービスを更新する方法として、新しい SD ファイルを保存し、サービスを削除して、更新した SD を公開することをお勧めします。
この方法では、上記の公開の場合と同じスクリプト例を使用してサービスの更新も実行できます。 更新するサービスのみを含むようにその入力ファイルを変更するだけです。 既存のサービスが見つかった場合、スクリプトは SD をアップロードする前にそのサービスを削除します。
この方法でサービスを更新した後、サービスが使用する SOE をすべて再有効化します。
代わりに、ArcGIS REST API を使用して、スクリプトで (マップまたはソース ドキュメントではなく) サービス プロパティを更新することもできます。
データの同期
複数の環境間で確実にデータが同期されるようにします。 これには、ジオデータベース レプリケーションが役立ちます。 または、古いデータセットを新しいデータセットに完全に置き換えることもできます。 たとえば、ファイル ジオデータベースを削除して、更新されたファイル ジオデータベースに置き換えることができます。
テーブルまたはファイル ジオデータベースを完全に置換する場合は、ArcGIS Server サービスが、基になるデータセットのスキーマをデフォルトでロックすることに注意してください。 スキーマがロックされている場合は、データを置換する前にサービスを停止します。 マップ サービスの場合は、いくつかの点に注意してスキーマのロックを無効化することができますが、その他のサービス タイプではロックを無効化することはできません。
アプリケーションの更新
開発、ステージング、および本番環境の間でアプリケーションを移動するには、アプリケーション ファイルをサイト間でコピーし、コードに記述されている Web サービスの URL を新しいサイトに合わせて更新します。 サービスの URL を定義するには、構成ファイルを使用します。
コード内の URL を更新する際に、次に示すスクリプトを使用できます。 このコードは、指定したフォルダー内のファイルを再帰的に検索し、「http://myDevServer/arcgis」などの特定の文字列を検索して、ステージング サイトまたは本番サイトの場所 (「http://myProdServer/arcgis」など) で置換します。
このスクリプトを開始する前に、元のアプリケーション ファイルのバックアップ コピーを作成してください。 また、スクリプトには処理するテキスト ファイルの拡張子を指定できます。たとえば、ArcGIS API for JavaScript ファイルの場合は「.js」や「.html」を指定できます。
スクリプトを使用して URL を置換したら、アプリケーション ファイルをワークフローの次のサーバー (ステージングまたは本番) にコピーします。
import os
import sys
import shutil
import traceback
def dirEntries(dir_name, subdir, *args):
'''Return a list of file names found in directory 'dir_name'
If 'subdir' is True, recursively access subdirectories under 'dir_name'.
Additional arguments, if any, are file extensions to match filenames. Matched
file names are added to the list.
If there are no additional arguments, all files found in the directory are
added to the list.
Example usage: fileList = dirEntries(r'H:\TEMP', False, 'txt', 'py')
Only files with 'txt' and 'py' extensions will be added to the list.
Example usage: fileList = dirEntries(r'H:\TEMP', True)
All files and all the files in subdirectories under H:\TEMP will be added
to the list.
'''
fileList = []
for file in os.listdir(dir_name):
dirfile = os.path.join(dir_name, file)
if os.path.isfile(dirfile):
if not args:
fileList.append(dirfile)
else:
if os.path.splitext(dirfile)[1][1:] in args:
fileList.append(dirfile)
# recursively access file names in subdirectories
elif os.path.isdir(dirfile) and subdir:
print "Accessing directory:", dirfile
fileList.extend(dirEntries(dirfile, subdir, *args))
return fileList
def updateString(infileName, srchString,rplString):
bakFileName = os.path.splitext(infileName)[0] + ".bak"
if not os.path.exists(bakFileName):
# copy the original file
shutil.copy(infileName, bakFileName)
# Open the backup (= original) file to read
inFileHndl = open(bakFileName,"r")
outFileHndl = open(infileName,"w")
for line in inFileHndl:
if line.find(searchString) > 0:
line = line.replace(searchString, replaceString)
outFileHndl.write(line)
outFileHndl.close()
inFileHndl.close()
# remove the backup (=original content file)
os.remove(bakFileName)
if __name__ == '__main__':
try:
inFolder = r"C:\inetpub\wwwroot\viewer" # path to search
searchString = "http://mydevserver" # string to find
replaceString = "http://mystgserver" # string - replace searchString with replaceString
fList = dirEntries(inFolder, True, 'xml')
for f in fList:
updateString(f, searchString, replaceString)
print '\n\n\n' + 'Process Complete'
except:
# Return any python specific errors as well as any errors from the geoprocessor
#
tb = sys.exc_info()[2]
tbinfo = traceback.format_tb(tb)[0]
pymsg = "PYTHON ERRORS:\nTraceback Info:\n" + tbinfo + "\nError Info:\n " + \
str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"
print '\n\n\n' + pymsg