Skip To Content

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

许多组织使用单独的开发、过渡和生产环境来维护其网站的质量。 在您的 ArcGIS Enterprise 组织中使用时,这些环境通常以如下方式进行设置:

  • 开发 - 此为沙盒环境,您可以在其中测试应用程序和服务,而不会对开发环境造成影响。 通常,开发环境在与生产 ArcGIS Enterprise 环境断开连接的小型计算机上运行。 一旦在开发环境中验证了更改,便将其应用于过渡环境。
  • 过渡 - 此环境是生产环境的克隆环境或其他近似环境。 过渡环境用于构建和测试增值应用程序和地图缓存,执行其他第三方软件的用户验收、性能和负载测试,组织新商业数据的更新以及开展培训活动。 在此级别测试将决定在生产环境应用更改或拒绝更改并等待开发环境的新迭代。 过渡站点不用于开发,仅用于性能和功能测试。 EsriArcGIS Enterprise 提供的过渡许可比生产许可成本低。
  • 生产 - 由于 GIS 用户(在某些情况下是公众)可以访问此环境,因此在此环境中绝对不会进行任何开发或测试。 只有通过过渡站点中的测试详查的更改才会应用于生产站点。

在理想情况下,开发、过渡和生产环境使用不同的数据库和基础架构。 每个组织都有如何在环境中测试和批准更改的特有规则。

在环境间移动更改可能面临逻辑挑战。 该帮助主题提供了模式和脚本来指导您完成此过程,无论您的 ArcGIS Server 站点是与门户联合还是独立的。

注:

此主题讨论 ArcGIS Server 在开发、过渡和生产环境中的注意事项。 它不涵盖其他 ArcGIS Enterprise 组件。

配置每种环境

在每种环境中,安装 ArcGIS Server、创建站点并配置安全性、服务器对象扩展模块 (SOE) 和其他设置。 尽管可以使用脚本进行自动化,但是如果手动执行这些任务中的大多数任务,将会更快。

首先运行开发站点,然后创建过渡站点,最后创建生产站点。

部署服务

在多种环境中部署服务的关键是向 ArcGIS Server 正确注册文件夹和数据库并使用服务定义 (SD) 进行发布。

将文件夹和数据库注册到 ArcGIS Server

ArcGIS Server 注册文件夹或数据库时,请提供发布者的数据路径和服务器的路径。

  • 发布者的路径是计算机中将用于创建 SD 文件的数据路径。 在开发、过渡和生产服务器上注册项目时,发布者的路径始终相同。
  • 服务器的路径是服务器上的数据路径。 在开发、过渡和生产服务器上注册项目时,此路径可能不同。

如果要注册多个文件夹或数据库,可以考虑使用脚本。 示例:注册文本文件中列出的文件夹和数据库使用 ArcPy AddDataStoreItem 函数注册文本文件中提供的文件夹和数据库连接列表。 您需要针对每种环境修改文本文件。

发布服务

在多种环境中,部署服务时使用 SD 文件。 SD 文件获取发布服务所需的信息并将其打包为一个便携式文件。 虽然可以将 GIS 数据打包到 SD 文件中,但将数据预加载到每种环境中并使用副本保持同步可能更加高效。

创建中性连接 SD 文件(在保存服务定义向导中选择无可用连接选项),这样,便可在任意服务器上灵活发布文件。 在发布 SD 文件时,ArcGIS Server 将自动更正写入 SD 的路径,以便使用您的服务器路径。 因此,必须认真注册数据才能在多种环境中部署同一 SD 文件。

发布服务是非常适合脚本编写的任务。 您可以使用 ArcPy 函数上传服务定义,以创建将发布每个 SD 的脚本。

使用脚本将 SD 文件部署到不同环境。

从 SD 文件部署服务后,需要启用这些服务所需的任何扩展模块。 您可以手动操作或编写脚本以完成操作。

另一个可以编写脚本的任务是按照文本文件的说明应用不同服务的权限。

更新服务

有时,您可能想要更新服务以便使用新属性或反映源文档中的更改,例如 ArcGIS Pro 工程中一组永久的符号系统编辑内容。 在多种环境中更新服务的建议方法:保存新的 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