开发、过渡和生产环境下的 ArcGIS Server

许多组织使用单独的开发、过渡和生产环境维护其网站的质量。以下为涉及 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 文件部署到不同环境

部署完 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
6/13/2014