客户端服务器模式

​ 在客户端服务器模式下,包含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上通过时间戳检查当前知识包有没有更新,如果有更新则取到客户端,同时更新客户端缓存里对应的知识包;如果没有更新,那么就直接采用当前客户端缓存里的知识包。

urule.knowledgeUpdateCycle属性默认值为0,一般情况下,如果我们的客户端为一个Java Web应用,只需要将这个属性置为1即可,因为客户端为Web应用,服务端会通过推送方式让客户端知识包与服务端时刻保持一致。

​ 如果客户端为非Web应用,那么才需要修改urule.knowledgeUpdateCycle属性值为一个大于1的数值,以实现定期检查服务端知识包是否有更新功能。

搭建Server应用

​ 搭建URule Server应用的与安装与配置一节中介绍的完全相同,就是在一个普通的java web应用中将URule Pro Console模块和URule Pro Core添加进去。需要注意的是,在URule Server应用搭建好了之后,要保证“/urule/loadknowledge”这个URL在可以匿名访问,比如输入类似下面的地址,看看应用会有什么样的响应。

http://localhost:8080/urule-server/urule/loadknowledge

​ 在系统未登录的情况下,访问上述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>4.0.0</version>
</dependency>

​ 可以看到,在客户端当中就不再需要urule-console-pro模块了,只需要一个urule-core-pro模块即可。

上面的maven依赖中,我们使用的是4.0.0版本,实际使用时,可以在网页中打开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-4.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” 上请求对应的知识包。

如果同步不成功需要检查url配置,确保url的末尾没有添加/,例如:“http://192.168.18.11:8080/urule-server/” 是不允许的

URule Pro中提供了动态加载Jar包及Spring配置文件功能,在客户端配置了urule.resporityServerUrl属性后,客户端在启动时会自动到服务端检查是否有新的动态Jar文件信息需要加载,如果有则下载到客户端并加载,所以这时服务端的“urule/dynamic/checkLatestJarsDir”和“urule/dynamic/loadDynamicJars”这两个URL要保证匿名可访问(URULE框架默认允许匿名访问),否则客户端启动时会产生错误。

注意:当前如果客户端上配置了urule.resporityServerUrl属性值,但这个属性对应的Server不存在,或无法访问,那么客户端在启动到服务端检查是否有新的动态Jar文件信息需要加载操作就会报错,导致客户端启用失败。

​ 到这里,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上客户端配置

​ 如果当前登录用户为团队创建人员,那么在登录系统后,可以看到客户端配置入口,如下图:

​ 我们可以添中多个客户端,这样在当前项目发布知识包时就可以自动推送到这里的客户端上,如下图:

​ 配置完成后,进行项目的知识包管理页面,查看某个知识包的已发布知识包,在弹出窗口可以看到已发布的知识包列表,选中某条需要推送到客户端的知识包,点击右键,在弹出菜单中选择推送到客户端,如下图:

​ 点击该菜单项,系统会尝试向这些客户端推送当前发布的知识包对象,如果这些客户端是存在的,就可以发布成功,这样对应的客户端本地缓存中就会存储这个发布的知识包对象。

客户端动态配置

​ 实际使用时,我们可能会在诸如docker之类的容器中部署客户端应用,在这种情况下,客户端的IP地址不是固定的,此时要在服务端指定客户地址的话,采用上面的方法就行不通了。 ​ 为了兼容这种客户端IP地址动态变化的场景,URule Pro当中还提供了一个名为ClientProvider接口,通过实现这个接口来动态指定客户端IP地址,ClientProvider接口类源码如下:

package com.bstek.urule.console;

import java.util.List;

import com.bstek.urule.console.database.model.UrlConfig;

/**
* @author Jacky.Gao
* @since 2021年9月26日
*/
public interface ClientProvider {
    List<UrlConfig> loadClients(String groupId);
}

​ 实现了ClientProvider接口后,只需要将实现类配置到Spring上下文当中,使之成为一个标准的Spring Bean即可,这样引擎在获取配置的客户端信息时就会尝试从这个实现类中获取。

​ 一旦我们实现了该接口,并将其配置到Spring中,重启应用,在客户端配置页面就可以看到该接口实现类中加载的客户端列表,同时该页面也不再提供客户端信息的编辑功能。

Spring-Cloud框架

例如在spring-cloud中我们可以通过DiscoveryClient的getInstances获得对应服务的ip地址列表 参考代码:

public class MemberClientProvider implements ClientProvider {

    @Override
    public List<UrlConfig> loadClients(String arg0) {
        List<ServiceInstance> instances = Utils.getApplicationContext().getBean(DiscoveryClient).getInstances("consul-member");
        List<UrlConfig> clients = new ArrayList<UrlConfig>();
        for (ServiceInstance instance:instances) {
            UrlConfig client = new UrlConfig();
            client.setName(instance.getHost());
            client.setType(UrlType.client);
            client.setGroupId("bstek");
            client.setUrl("http:"+instance.getHost()+":"+instance.getPort());
            clients.add(client)j;
        }
        return clients;
    }

}

K8S

如果不是spring-cloud框架,直接K8S部署,可以通过K8S提供的client-java的SDK获取到IP地址列表,详细办法参考K8S官方文档。 一篇简单的参考文档:

http://events.jianshu.io/p/d8a073f8d416

前面我们介绍了在URule Pro客户端中配置“urule.knowledgeUpdateCycle”属性的含义及目的,对于客户端为Web应用类型,一旦我们在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,这样可以减少不必要的调试信息输出,可显著提升性能。

results matching ""

    No results matching ""