开发、过渡和生产环境下的 ArcGIS Server
许多组织使用单独的开发、过渡和生产环境维护其网站的质量。以下为涉及 ArcGIS Server 时各个环境的情况:
- 开发 - 这是一个 ArcGIS Server 沙盒站点,可供自由测试应用程序和服务。通常情况下,开发站点会使用 ArcGIS Server 的 Esri 开发者网络 (EDN) 许可运行于小型计算机。在开发站点验证所有更改后,这些更改内容会应用到过渡站点。
- 过渡 - 此 ArcGIS Server 站点是生产站点的克隆版本。在这一级别进行测试需要决定:是将更改内容应用于生产站点还是拒绝更改并等待来自开发站点的新迭代。过渡站点不用于开发,仅用于性能和功能测试。Esri 能够为 ArcGIS Server 用户提供比生产许可成本更低的过渡许可。
- 生产 - 此站点为业务工作流提供实际支持,是实际用户所访问的站点。绝对不会在此站点进行开发或测试。只有通过过渡站点中的测试详查的更改才会应用于生产站点。
在理想情况下,开发、过渡和生产环境使用不同的数据库和基础架构。各个组织对于如何测试更改以及如何跨站点批准更改均有自己的规则。
在站点之间移动更改时会面临逻辑方面的问题。本帮助主题将提供模式和脚本,引导您完成整个过程。
配置各个环境
在各个环境下,用户均需安装 ArcGIS Server、创建站点和配置安全性、服务器对象扩展 (SOE) 以及其他设置。尽管可以使用示例:通过两个文本文件创建用户和角色等脚本,在手动执行时,大部分任务都可以更快完成。.
首先运行开发站点。然后创建过渡站点,随后创建生产站点。
部署服务
在多种环境中部署服务的关键是向 ArcGIS Server 正确注册文件夹和数据库并使用服务定义 (SD) 进行发布。
将文件夹和数据库注册到 ArcGIS Server
向 ArcGIS Server 注册文件夹或数据库时,请提供发布者的数据路径和服务器的路径。
- 发布者的路径是将用于生成 SD 文件的计算机上的数据路径。在开发、过渡和生产服务器上注册项目时,发布者的路径始终相同。
- 服务器的路径是服务器上的数据路径。当用户在开发、过渡和生产服务器上注册项目时,此路径会有所区别。
如果要注册多个文件夹或数据库,可以考虑使用脚本。示例:注册文本文件中列出的文件夹和数据库使用 ArcPy AddDataStoreItem 函数注册文本文件中提供的文件夹和数据库连接列表。用户应修改各个环境下的文本文件。
发布服务
在多个环境下部署服务时需使用 SD 文件。SD 文件获取发布服务所需的信息并将其打包为一个便携式文件。尽管可以将 GIS 数据打包到 SD 文件,但将数据预加载到各个环境并使用复制功能来保持数据同步的方法可能更为简单。
创建中性连接 SD 文件(在保存服务定义 向导中选择无可用连接选项),这样,便可在任意服务器上灵活发布文件。在发布 SD 文件时,ArcGIS Server 将自动更正写入 SD 的路径,以便使用您的服务器路径。因此,您必须认真注册数据,才能在多种环境中部署同一 SD 文件。
发布服务任务非常适合脚本。示例:发布文本文件中列出的服务定义将读取文本文件并发布其中的所有 SD 文件。脚本使用 ArcPy 函数 Upload Service Definition 发布每个 SD 文件。

部署完 SD 中的服务后,必须启用服务所需的所有 SOE。也可手动或通过编写脚本方式完成此操作。
应用权限是需要编写脚本的另一任务。示例:通过文本文件应用权限使用 ArcGIS REST API 按照文本文件的说明应用不同服务的权限。
更新服务
有时,用户可能想要更新某项服务,从而使用新属性或者反映源文档中的变化,例如 ArcMap 文档 (MXD) 中的一组永久性符号系统编辑内容。在多个环境下更新服务时建议采用的方法是,保存一个新 SD 文件,然后删除服务并发布更新后的 SD 文件。
采用这种方法时,发布时使用的上述相同示例脚本也可以执行服务更新。只需修改输入文件,使其只包含您想要更新的服务。如果找到现有的服务,在上传 SD 文件之前脚本会删除此服务。
采用这种方式更新服务后,需要重新启用服务使用的所有 SOE。
您也可以使用 ArcGIS REST API 中的编辑服务操作将服务属性(而非地图或源文档)更新脚本化。
保持数据同步
需要确保数据在多个环境下保持同步。地理数据库复制功能可帮助您完成此操作。此外,您还可以采用新数据集完全替换旧数据集。例如,您可以删除文件地理数据库并采用更新的文件地理数据库替换它。
如果决定完整地替换表格或文件地理数据库,请记住,ArcGIS Server 服务在默认情况下会锁定基础数据集的方案。如果方案被锁定,则需要停止服务才能替换数据。出于谨慎原因,您可以针对地图服务禁用方案锁定,但不能针对其他服务类型禁用方案锁定。
更新应用程序
要在开发、过渡和生产环境中移动应用程序,您可以将应用程序文件从一个站点复制到另一个站点,然后更新代码中的所有 Web 服务 URL,使它们指向新站点。使用配置文件定义服务的 URL。
以下脚本可以帮您更新代码中的 URL。这些代码可用于递归查找所提供文件夹中的文件,搜索特定字符串(例如 http://myDevServer/arcgis),然后使用过渡或生产站点的位置(例如 http://myProdServer/arcgis)替换这个字符串。
在启动此脚本之前,应该对原始应用程序文件进行备份。还需注意,此脚本允许您指定想要处理的文本文件的扩展名,例如为 ArcGIS Viewer for Flex 配置文件指定 .xml,为 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