16.客户端服务器配置
概述
URule Pro支持三种运行模式,分别是嵌入模式、分布式计算模式以及独立服务模式,实际使用时,根据项目情况三选一即可。
所谓的嵌入模式就是将URule嵌入到目标应用当中运行,这种模式的特点部署起来简单、方便,便于系统开发与调试; 分布式计算模式就是把计算分布到各个应用当中,规则服务器只负责规则的构建、打包与测试,具体的规则计算发生在计算应用当中,规则服务器通过Http协议将知识包推送到各个计算应用,分布式计算模式适用于单个服务器不强,规则计算时需要的输入数据结构复杂的情况。
最后一种就是独立服务模式,这种模式也是传统规则引擎采用的模式,那就是规则服务器通过暴露Restful服务来接收各种类型规则计算请求,请求把输入数据以JSON格式提供,在一台服务器上完成所有类型的规则计算,计算完成后再把输出数据以JSON格式返回, 在第22小节知识包Restful服务暴露与调用中详细介绍了这种模式的配置及使用方式,本小节将只对嵌入模式和分布式计算模式两种类型结构进行介绍。
在之前介绍的内容当中,安装与配置一节介绍的项目创建配置方式就是采用的嵌入模式,在嵌入式模式下URule Pro相关Jar包与业务应用一起打包,作为一个应用来进行部署,这种模式结构比较简单,开发、部署起来都比较容易。
再来看看分布式计算模式示意图:
在分布式计算模式下,包含URule Pro Console模块的应用被部署成一个独立的Server,在这个Server上创建规则项目,在项目中根据业务需求添加决策集、决策表、交叉决策表、决策树、评分卡、复杂评分卡、决策流等,再把这些文件打包到知识包中,最后通过HTTP协议暴露给各个客户端业务系统使用。
分布式计算模式下客户端获取服务端知识包的方式:
在分布式计算模式下,URule Server上给客户端提供的是若干个已经构建好的知识包对象,当有客户端需要进行规则计算时,它会检查当前客户端中配置的“urule.knowledgeUpdateCycle”属性值,如果为0,那么就直接请求URule Server获取指知识包;如果为1,那么它会首先检查客户端本地缓存当中是否存在指定的知识包,如果存在,就取本地缓存中的,如果不存在,则到URule Server下请求指定的知识包,然后将请求到的知识包缓存到客户端内存中,这样下次就不再到URule Server上下载;如果“urule.knowledgeUpdateCycle”属性值大于1,那么客户端会首先检查本地缓存中是否存在指定的知识包,如果存在,那么就拿当前时间与本地缓存中的知识包的时间戳进行比较,如果小于“urule.knowledgeUpdateCycle”属性值,那么就直接取这个知识包,如果大于它,那么就到URule Server上通过时间戳检查当前知识包有没有更新,如果有更新则取到客户端,同时更新客户端缓存里对应的知识包;如果没有更新,那么就直接采用当前客户端缓存里的知识包。。
搭建Server应用
搭建URule Server应用的与安装与配置一节中介绍的完全相同,就是在一个普通的java web应用中将URule Pro Console模块和URule Pro Core添加进去。需要注意的是,在URule Server应用搭建好了之后,要保证“/urule/loadknowledge”这个URL在可以匿名访问,比如输入类似下面的地址,看看应用会有什么样的响应。
在系统未登录的情况下,访问上述URL看到的不是一个登录页面,那么就说明“/urule/loadknowledge”这个URL在可以匿名访问,是OK的。
如果出现我们应用中的登录界面之类,那就说明“/urule/loadknowledge”这个URL被我们自己系统内部的权限模块给拦截了,需要我们在系统中对内部的权限进行配置,使得“/urule/loadknowledge”URL在可以匿名访问。做好这个工作,那么URule Server的搭建工作就完成了,下面我们看看如果配置客户端应用。
配置客户端应用
配置客户端应用,首先要解决的是如果将URule Pro客户端所需要的jar包添加到项目中,这里我们分maven项目以及非maven项目分别进行讨论。
maven项目配置
如果当前客户端是基于maven的项目,那么我们需要在其pom.xml中添加以下依赖:
<dependency>
<groupId>com.bstek.urule</groupId>
<artifactId>urule-core-pro</artifactId>
<version>3.0.3</version>
</dependency>
可以看到,在客户端当中就不再需要urule-console-pro模块了,只需要一个urule-core-pro模块即可。
上面的maven依赖中,我们使用的是3.0.3版本,实际使用时,可以在网页中打开https://search.maven.org/,查询“urule-core-pro”关键字,找到最新的urule-core-pro的版本信息,以确定在依赖中version位置要输入的版本号信息。
到这里,pom的配置就完成了,我们再来看看一个标准的非maven的Web项目如何配置成URule Pro客户端。
非maven项目配置
如果是一个非maven普通的java web项目,添加URule Pro客户端就是将urule-core-pro的jar包及其依赖的第三方jar包放到客户端应用的/WEB-INF/lib目录下即可,urule-core-pro的jar包我们可以到https://search.maven.org/上下载最新的urule-core-pro-2.x的jar包,对于依赖的第三方jar包,可以点击此处下载。
加载spring配置文件
URule Pro客户端所需要的jar包添加到客户端项目中后,接下来我们还需要加载urule-core-pro模块中的spring配置文件。urule-core-pro模块中的spring配置文件位于classpath根下,名为urule-core-context.xml。
如果我们的客户端项目没有采用spring框架,那么可以在web.xml中添加如下所示Listener来加载urule-core模块中的spring配置文件:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:urule-core-context.xml</param-value>
</context-param>
如果我们的项目也采用了spring框架,那么只需要打开项目中任意一个spring配置文件,在其中添加如下配置即可:
<import resource="classpath:urule-core-context.xml"/>
这样urule-core-pro的spring配置文件的加载配置就完成了。
配置服务器地址
对于URule Pro客户端应用来说,在进行规则计算时,如果客户端本地缓存没有相应的知识包,那么它会到URule Server上请求对应的知识包,要给URule Pro客户端应用配置对应的URule Server地址,我们需要添加一个properties文件,比如在项目的WEB-INF目录下新建一个名为configure的properties文件,然后在我们项目中任意一个spring配置文件中添加如下配置加载这个properties文件:
<bean parent="urule.props">
<property name="location">
<value>/WEB-INF/configure.properties</value>
</property>
</bean>
打开这个configure.properties文件,在其中添加一个名为“urule.resporityServerUrl”属性,比如 urule.resporityServerUrl=http://192.168.18.11:8080/urule-server , 就表明我们为当前URule客户端应用配置的URule Server为“http://192.168.18.11:8080/urule-server”,这样在进行规则计算时,如果客户端本地缓存没有相应的知识包,那么它会到“http://192.168.18.11:8080/urule-server”上请求对应的知识包。
从2.1.1版本开始,urule-pro提供了动态加载Jar包及Spring配置文件功能,具体见21.Spring Bean及Java类的热部署描述,如果我们使用的是urule-pro-2.1.1及以上版本, 那么在采用客户端服务器模式配置应用时,客户端配置了“urule.resporityServerUrl”属性后,客户端在启动时会自动到服务端检查是否有新的动态Jar文件信息需要加载,如果有则下载到客户端并加载, 所以这时服务端的“urule/dynamic/checkLatestJarsDir”和“urule/dynamic/loadDynamicJars”这两个URL要保证匿名可访问,否则客户端启动时会产生错误。
到这里,URule Pro客户端的配置就全部完成了,通过指定urule.resporityServerUrl属性值,我们的客户端无论是标准的Java Web应用还是普通的Java应用,都可以与URule Server连接,从而在运行时获取到相应的知识包。
但是,如果我们的客户端应用是标准的Java Web应用,那么除了可以通过urule.resporityServerUrl属性指定URule Server地址,从而主动获取知识包外,还可以通过配置一个Servlet被动接收URule Server推送过来的知识包,这样模式,相比主动获取知识包方式要高效的多,同时还可以时刻与Server上的知识包保持同步。
下面就来看看如何给一个类型为标准Java Web应用的客户端配置接收服务端推送过来知识包的Servlet。
配置web.xml
在之前内容中我们就提过,URule Pro的客户端即可以是标准的Java Web应用,也可以是普通的Java应用。如果是普通Java应用,那么上面的那么配置就可以了;如果是标准的Java Web应用,那么我们还可以做些配置,使得其以主动接收来自URule Server上推送过来的最新的知识包。
对于URule Server来说,如果在规则项目中配置了URule的客户端地址,那么在知识包发布时会自动推送到这些客户端。所以我们的URule Pro客户端如果是个标准的Java Web应用,那么可以配置一个可以接收URule Server推送的知识包的Servlet。
打开项目的web.xml,在其中添加如下servlet配置:
<servlet>
<servlet-name>uruleClientServlet</servlet-name>
<servlet-class>com.bstek.urule.KnowledgePackageReceiverServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>uruleClientServlet</servlet-name>
<url-pattern>/knowledgepackagereceiver</url-pattern>
</servlet-mapping>
在上面的servlet配置中,url-pattern项的“/knowledgepackagereceiver”值是固定的,不能修改为其它值,否则将无法收到URule Server上推送过来的知识包。 同时,客户端中的这个用于接收知识包推送的Servlet还要保证其可以匿名访问,也就是客户端中如果被权限框架包裹,那么要保证“/knowledgepackagereceiver”这个URL在不登录的情况下就可以访问, 否则服务端将无法把知识包推送到目标客户端。
要实现推送功能,除了要配置对应Java Web客户端上的Servlet,还需要在URule Server上对可以接收推送的客户端进行定义。
URule Server上客户端配置
打开URule Pro的控制台,在规则项目中点击右键,在弹出的菜单中选择“配置接收推送客户端”,就可以打开客户端配置页面,如下图:
我们可以添中多个客户端,这样在当前项目发布知识包时就可以自动推送到这里的客户端上,如下图:
配置完成后,点击当前项目的“知识包”节点,选择任意一个知识包,在知识包操作菜单中点击“发布新知识包”菜单项,知识包发布成功后会看到如下图所示的提示:
点击“确定”,系统会尝试向这些客户端推送当前发布的知识包对象,如果这些客户端是存在的,就可以发布成功,这样对应的客户端本地缓存中就会存储这个发布的知识包对象。
实际使用当中,如果希望向客户端推送某个已发布的知识包版本,我们也可以点击知识包操作菜单中“已发布的知识包”菜单项,在弹出的窗口当中,可以看到所有已经发布的知识包列表,如下图所示:
如果需要将某个知识包推送到客户端,那么可以点击上图中红框内按钮,这样就可以将当前版本知识包推送到客户端当中。
客户端动态配置
实际使用时,我们可能会在诸如docker之类的容器中部署客户端应用,在这种情况下,客户端的IP地址不是固定的,此时要在服务端指定客户地址的话,采用上面的方法就行不通了。 为了兼容这种客户端IP地址动态变化的场景,URule Pro当中还提供了一个名为ClientProvider接口,通过实现这个接口来动态指定客户端IP地址,ClientProvider接口类源码如下:
package com.bstek.urule.console.repository;
import java.util.List;
/**
* @author Jacky.gao
* @since 2019年12月29日
*/
public interface ClientProvider {
/**
* @param project 规则项目名称
* @param all 是否加载所有的客户端信息,如果为true,则包括禁用的客户端信息
* @return 返回客户端地址的集合
*/
List<ClientConfig> loadClients(String project,boolean all);
}
实现了ClientProvider接口后,只需要将实现类配置到Spring上下文当中,使之成为一个标准的Spring Bean即可,这样引擎在获取配置的客户端信息时就会尝试从这个实现类中获取。 下面是我们编写的一个测试用的ClientProvider接口实现类:
package test;
import java.util.ArrayList;
import java.util.List;
import com.bstek.urule.console.repository.ClientConfig;
import com.bstek.urule.console.repository.ClientProvider;
public class TestClientProvider implements ClientProvider {
@Override
public List<ClientConfig> loadClients(String project, boolean all) {
List<ClientConfig> list=new ArrayList<ClientConfig>();
ClientConfig cc=new ClientConfig();
list.add(cc);
cc.setName("测试");
cc.setClient("www.baidu.com");
cc.setEnabled(true);
cc.setProject("保险行业示例项目");
return list;
}
}
将该实现类配置到Spring当中,重启应用,再次打开项目中“配置接收推送客户端”页面,则会看到如下图所示效果:
可以看到当前页面会把实现类中配置的客户端信息展示出来,同时该页面也不再提供客户端信息的编辑功能。
前面我们介绍了在URule Pro客户端中配置“urule.knowledgeUpdateCycle”属性的含义及目的,一旦我们在URule Server中配置了客户端地址,那么知识包每次发布都会被推送到这些客户端。这样在生产环境下,对于客户端来说,“urule.knowledgeUpdateCycle”属性值只要设置成1即可,也就是每次都在客户端本地缓存中查找目标知识包是否存在,如果存在直接使用。如果知识包有更新,URule Server会动推送到目标客户端,对于客户端来说直接从本地缓存中就可以取到最新的知识包,这样可以剔除所有不必要的客户端与服务端的交互,节省网络资源,同时可以大幅提高客户端规则计算性能。
我们在对URule Pro进行性能测试时,一定要将“urule.knowledgeUpdateCycle”属性值只要设置成1,因为“urule.knowledgeUpdateCycle”属性值默认为0,所以每次执行规则都会编译一次规则包,这样会带来很差的测试结果,所以这点非常关键; 在客户端中,将“urule.knowledgeUpdateCycle”设置成1后,检验该属性是否生效最好的方法是在客户端调用服务端知识包时观察控制台是否有类似“Load knowledgepackage [ packageId ] from remote...”这样的字符输出,如果有类似输出,则说明urule.knowledgeUpdateCycle=1未生效, 我们需要进一步检查配置,找到未生效的原因。 同时,名为"urule.debug"的属性也会对性能产生一点影响,这个属性值默认为true,表示允许进行调试信息输出,这样对于性能测试来说无疑会造成影响,所以在性能测试或生产环境中建议将“urule.debug”属性设置为false,这样可以减少不必要的调试信息输出,可显著提升性能。