扩展集群过滤器 |
利用 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 的主要方法如下:
1 | 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 字段值。
示例如下:
1 2 3 4 5 6 | @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/>添加子节点如下:
1 2 3 4 5 6 7 8 9 10 | < 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 的节点进行过滤,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 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/>节点中添加温度服务提供者的配置,即:
1 2 3 4 5 6 7 8 | < 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:
1 2 3 4 5 6 7 8 9 | < 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/>节点中添加子节点如下:
1 2 3 4 5 6 7 8 9 10 | < clustering > ... < clusterService > ... < clusterServiceFilters > < ClusterServiceFilter name = "cityNameFilter" class = "com.supermap.sample.cluster.CityNameFilter" > </ ClusterServiceFilter > </ clusterServiceFilters > </ clusterService > </ clustering > |
S1、S2作为子节点,需要向 C1集群服务器报告,在 S1、S2的系统配置文件 iserver-system.xml 配置集群报告器如下:
1 2 3 4 5 6 7 8 | < 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的天气预报服务,从而保证了结果的正确性。