扩展集群过滤器 |
利用 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 集群的示例中,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(".")>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的天气预报服务,从而保证了结果的正确性。