利用 SuperMap iServer 提供的集群机制,不仅可以搭建普通的领域空间服务(DSS)集群,还可以搭建分布式 DSS 集群。分布式 DSS 集群,是指将提供不同服务能力的同类 DSS 进行集群,如在天气查询 DSS 里,不同的天气查询 DSS 可以提供不同城市的天气预报,可以对它们进行集群,共同提供所有城市的天气预报。

过滤器简介

为实现分布式 DSS 集群,SuperMap iServer 提供了过滤器机制,在集群服务器上,负载均衡前,先对 DSS 节点(包含集群服务器本身提供的 DSS)使用过滤器依次进行过滤,只保留能提供正确 DSS 的节点。

SuperMap iServer 提供了 com.supermap.services.cluster.client.spi.ClusterServiceFilter 接口,用户需要实现该接口对 DSS 节点进行过滤,ClusterServiceFilter 的主要方法如下:

boolean filter(ServiceInfo serviceInfo, HttpServletRequest request);

该方法用于根据客户端请求和 DSS 节点的信息对 DSS 节点进行过滤,其中,ServiceInfo.additions 属性为一个 String 数组,对应 DSS 的服务能力信息(由 NameMapping 提取),返回值为 true 表示过滤掉该 DSS 节点(不使用该节点),false 表示可以使用该节点提供的 DSS 服务(所有通过的节点,会在负载均衡后由其中一个提供服务)。

此外,实现 ClusterServiceFilter 时,需要添加@ClusterServiceFilterType 注记,@ClusterServiceFilterType 有两个必选元素:componentType 和 interfaceType,它们限定了过滤器可过滤的服务组件的类型和服务接口类型,即过滤器只对该种类型组合的服务实例起作用。

componentType 取值为:服务组件实现类的类名;

interfaceType 取值为:服务接口实现类的@protocol 注记的 name 字段值。

示例如下:

@ClusterServiceFilterType(componentType = "Temperature", interfaceType = "Jaxrs")
public class CityNameFilter implements ClusterServiceFilter{
        public boolean filter(ServiceInfo serviceInfo, HttpServletRequest request) {
                ...
        }
}

 

过滤器的配置

过滤器需要配置到集群服务器上,在系统配置文件 iserver-system.xml(位于%SuperMap iServer_HOME%/webapps/iserver/WEB-INF)中,<clusterService/>的<clusterServiceFilters/>子节点配置,向<clusterServiceFilters/>添加子节点如下:

<clustering>
        ...
        <clusterService>
                ...
                <clusterServiceFilters>
                        <ClusterServiceFilter name="cityNameFilter" class="com.supermap.sample.cluster.CityNameFilter">
                        </ClusterServiceFilter>
                </clusterServiceFilters>
        </clusterService>
</clustering>

注意:可以实现多个过滤器,同时配置在<clusterServiceFilters/>节点中,过滤器会按照 name 节点的值进行排序,然后依次执行。

<ClusterServiceFilter/>还可以有 componentName 和 interfaceName 两个可选属性,可以进一步指定过滤器起作用的范围。

 

构建分布式天气预报 DSS 集群

在天气查询 DSS 集群的示例中,com.supermap.sample.cluster.CityNameFilter 实现了 ClusterServiceFilter 接口,可以对提供天气预报 DSS 的节点进行过滤,代码如下:

package com.supermap.sample.cluster;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import com.supermap.services.cluster.ServiceInfo;
import com.supermap.services.cluster.client.spi.*;
import com.supermap.services.components.spi.ClusterServiceFilterType;
@ClusterServiceFilterType(componentType = "Temperature", interfaceType = "Jaxrs")
public class CityNameFilter implements ClusterServiceFilter{
        @Override
        public boolean filter(ServiceInfo serviceInfo, HttpServletRequest request) {
                boolean returnvalue=true;
                //子节点附加信息中标识的可提供天气预报的城市名称
                String[] cityNames=serviceInfo.additions;
                
                if(cityNames==null){
                        return true;
                }
                //请求信息中的城市名。
                String requestCityName;
                String requestURI=request.getRequestURI();
                int left=requestURI.lastIndexOf("/")+1;
                if(left>0&&requestURI.lastIndexOf(".")&gt;left){
                        int right=requestURI.lastIndexOf(".");
                        requestCityName=requestURI.substring(left, right);
                }else{
                        requestCityName=requestURI.substring(left);
                }
                try {
                        requestCityName = URLDecoder.decode(requestCityName, "utf-8");
                } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                }
                for(int i=0;i<cityNames.length;i++){
                        if(requestCityName.equalsIgnoreCase(cityNames[i])){
                                returnvalue=false;
                        }
                }
                return returnvalue;
        }
}

将天气查询 DSS 集群示例编译后的 jar 包部署到三个 SuperMap iServer 服务器——C1、S1、S2的%SuperMap iServer_HOME%/webapps/iserver/WEB-INF/lib 目录下,C1只提供“杭州”的天气预报,S1只提供“成都”的天气预报,S2只提供“北京”的天气预报。

在服务配置文件 iserver-services.xml(位于%SuperMap iServer_HOME%/webapps/iserver/WEB-INF)中的<providers/>节点中添加温度服务提供者的配置,即:

<providers>
<provider class="com.supermap.sample.temperature.TemperatureProvider" 
 name="tempratureProvider">
<config class="com.supermap.sample.temperature.FileSetting">
<filePath>F:\C1.txt</filePath>
</config>
</provider>
</providers>

注意:C1.txt 为 C1服务器使用的数据,需要手工 Copy 到对应目录。配置 S1、S2服务器的温度服务提供者同上,分别使用 S1.txt、S2.txt 即可。

配置 C1、S1、S2服务器的温度服务提供者,在服务配置文件 iserver-services.xml 中的<components/>节点中添加温度组件的配置如下,其中,温度组件使用到了 ugcMapProvider-China400和 tempratureProvider:

<components>
<component class="com.supermap.sample.temperature.Temperature" 
 interfaceNames="restjsr" name="temperature-China" 
 providers="ugcMapProvider-China400,tempratureProvider">
<config class="com.supermap.sample.temperature.TemperatureParam">
<mapName>China</mapName>
</config>
</component>
</components>

C1作为集群服务器,构建集群(参见搭建领域空间服务集群),需要在 C1上配置过滤器,即 com.supermap.sample.cluster.CityNameFilter。打开 C1的系统配置文件 iserver-system.xml(位于%SuperMap iServer_HOME%/webapps/iserver/WEB-INF),在<clusterServiceFilters/>节点中添加子节点如下:

<clustering>
        ...
        <clusterService>
                ...
                <clusterServiceFilters>
                        <ClusterServiceFilter name="cityNameFilter" class="com.supermap.sample.cluster.CityNameFilter">
                        </ClusterServiceFilter>
                </clusterServiceFilters>
        </clusterService>
</clustering>

S1、S2作为子节点,需要向 C1集群服务器报告,在 S1、S2的系统配置文件 iserver-system.xml 配置集群报告器如下:

<clustering>
<reporters>
<reporter>
  <enabled>true</enabled>
  <address>http://C1:8090/iserver/services/cluster</address>
</reporter>
</reporters>
</clustering>

搭建的集群结构如下:

访问 C1获取“北京”的天气预报,即访问“http://C1:8090/iserver/services/Temperature/restjsr/北京”,C1会对集群中所有 DSS 节点进行过滤,获取能提供“北京”天气预报服务的 DSS 节点,这里是 S2,由 S2响应客户端请求(获取“北京”天气预报的请求),结果如下:

由于进行了过滤,DSS 集群在响应获取“北京”天气预报的请求时,不会使用到 C1、S1的天气预报服务,从而保证了结果的正确性。