ArcGIS Server Inside TM 三
——ArcGIS Server 配置参数
在前一篇中我主要给各位简单剖析了一下ArcGIS Server的各个组件,即SOM和SOC,SOM即服务对象管理器,主要负责客户端请求调度,服务对象管理以及内置负载均衡机制以便在合适的SOC机器中调度Server Object处理客户端请求。SOC即服务对象容器,主要负责承载各个池化、非池化服务器对象。由此我们可以看出,ArcGIS Server各个组件的负载主要承担在SOC上,而非SOM,所以我建议的部署策略是将SOM和Web服务器安装在一台机器上,SOC分离部署。其中,Web服务器主要负责发布各类Web服务以及Web应用程序。
ArcGIS Server支持两种服务端技术,即.NET技术和JAVA技术。.NET主要是基于Asp.NET架构,借助IIS服务器和Asp.NET管线机制发布ArcGIS Server的各类服务和ADF应用程序。如果您打算使用.NET架构的ArcGIS Server,我们建议您将ArcGIS Server的REST Application和ADF Application安装在IIS .NET不同的池中,也就是GIS服务池与您的基于Asp.NET的业务应用分别使用不同的IIS池,这样就可以避免一个出问题会牵连其他应用。
如果您使用的是JAVA架构,可选的Web容器有很多,TOMCAT、WebLogic、WebSphere等等,在此我不再赘述。有一种方案我觉得很是实用,Lighttd是开源领域应用非常广泛的一种Web容器,虽然它的动态处理能力非常弱,但是在处理静态资源时通常能够获得几十倍于TOMCAT的性能。所以我们可以使用Lighttd来发布ArcGIS Server的瓦片目录结构。这种方案一定能够给您带来极大的性能提升。
前面提到SOM主要负责管理服务器对象,我们可以通过ArcCatalog和ArcGIS Manager页面来进行管理,包括创建、删除、启动、停止服务等。在创建服务时我们需要配置的参数有很多,如池化、非池化,最大最小实例数、进程占用机制、进程回收机制以及服务请求等待时间等参数。这些参数到底对服务性能有何影响,下面我将重点进行描述。
池化服务和非池化服务:池化和非池化服务的主要区别是对象该在什么时候创建,池化服务就是在任何请求未到之前创建好一个或者多个服务器对象,如MapServer对象,当客户端请求到达SOC时,由SOC从池中找到可用的池化对象,并将其使用权限交给客户端,客户端在使用完该对象后及时调用ServerContext.RealeaseContext方法,以将对象放回池中,供其他客户程序调用。如果您使用ArcGIS Server ArcObjects API开发的话,在代码中及时释放ServerContext是非常重要的。如果客户强求到达SOC,恰恰池中没有可用的对象时,它会有两个选择:1)根据你配置的最大池化实例数和当前实例数目的关系决定是否动态创建池化对象;2)对请求进行排队,如果没有可用对象直到客户等待到最大等待时间,就是平时所说的超时,这时,SOC会给客户端返回一个超时的错误信息。如果你使用过Flex调用GP的话,我想你曾经肯定遇到过这个错误提示。非池化服务就是当请求达到时动态创建服务对像,虽然不需要提前创建对象,占用一定的内存资源,但由于经常动态创建对象,因此性能大都不如池化服务。如果是用Web ADF进行开发,并且将服务配置为非池化服务,ADF会给每个浏览器实例分配一个非池化实例,当这个浏览器实例关闭时非池化对象会被销毁。因此,在一个Web Application里面,并不是每次请求都需要创建对象实例,那样简直无法想象性能会有多低。
ArcGIS Server已经逐渐淘汰掉了Web ADF的开发方式,在ArcGIS Server10的下一个版本中也将取消非池化服务方式,全部采用池化服务。我们知道,以前做Web ADF在线编辑时,必须要求ArcGIS Server发布非池化服务,原因是非池化服务可以在不违反设计原则的情况下修改服务对象的状态(例如,你在服务器端动态添加一个图层,动态给添加一条记录等)。虽然池化服务你也可以修改它的服务器对象状态,但是一旦你修改状态就违反了重要的设计原则,即非池化服务是为无状态应用设计的。其实,ArcGIS Server所有的服务器对象如MapServer、GeometryServer、GeocodeServer、ImageServer等都是一种不维护状态的Utility Object,特别是GeometryServer,如果你要强跟我争论MapServer其实在内存中维护一个MXD\MSD的状态,我绝对同意你的看法。这里,我所说的状态是服务器端对象的状态,当然,客户端可以维护独立的地图状态,如当前地图窗口,图层显示与否等。
为了更加方便大家对池化服务和非池化服务的理解,我打一个简单的比方:生活中有时为了方便,午餐我们一般会选择一些“快”餐店,比如肯德基、麦当劳等。我认真思考了一下,他们为什么在我点餐到用餐的等待时间不超过10s呢,最主要的原因就是他们所有的“服务器对象”——汉堡、鸡腿等都是池化对象,也就是他们提前把这些东西都做好了,在等我们点餐呢。这些对象(汉堡、鸡腿)由于创建(烹饪、烘烤、油炸等工序)需要花费较长的时间,所以提前做好以备高峰并发访问,例如午餐用餐时。
在这里,有一点还需要提醒大家的就是,REST目前只支持池化服务,非池化在REST目录里面是没有信息的。所以我们有的朋友在创建完非池化服务后,到REST目录去查看却没有任何信息,请不要怀疑机器有问题,这是正常的。ArcGIS Server为什么不将非池化服务发布到REST中,原因很简单,大家思考思考吧。
关于进程占用机制其实也很容易理解,对于非池化服务,由于每个对象都是运行在独立的SOC进程中,即独占一个进程,所以与进程占用机制没有关系。只有池化服务才有进程占用一说,池化服务可以配置为高隔离的机制,就是每个池化对象运行在独立ArcSOC.exe进程中,也可以配置多个SOC实例运行在一个ArcSOC.exe进程中。ArcGIS Server低隔离机制默认是8个实例运行在一个SOC进程中,当然你可以进行修改。如果多个实例运行在一个进程中,ArcGIS会给每个实例创建线程,这些线程共享进程空间。优缺点其实就是进行和线程之间的差别,在此我就不多说了,可以翻阅一些《操作系统》相关的书籍。
ArcGIS Server还有一个比较有用的机制就是进程回收机制,我们可以将其配置如下:每天晚上12点定时执行进程回收。这到底有何用处呢?我们知道不管是池化对象还是非池化对象在系统内存长期运行不可避免会出现一些问题,例如其他程序的影响,客户的非法操作等会破坏对象的完整性。因此,我们需要在系统闲暇时重建这些对象。这就像一些剩菜剩饭,如果舍不得倒掉也需要定期清理,否则吃了会出毛病的。
最后给大家一点性能优化的小建议,建议服务器对象每个核配置2G内存,每个核配置2-3个实例,比如我的机器是4core,现在要发布一个动态地图服务,那么它的实力数可以配置在8-12个之间。如果您将服务经过切片处理,请不要设置如此多的实例数,配置了不但浪费内存反而提高不了速度,预知原因,请听下回分解。