URule Pro支持三種運(yùn)行模式,分別是嵌入模式、分布式計(jì)算模式以及獨(dú)立服務(wù)模式,實(shí)際使用時(shí),根據(jù)項(xiàng)目情況三選一即可。
所謂的嵌入模式就是將URule嵌入到目標(biāo)應(yīng)用當(dāng)中運(yùn)行,這種模式的特點(diǎn)部署起來(lái)簡(jiǎn)單、方便,便于系統(tǒng)開(kāi)發(fā)與調(diào)試; 分布式計(jì)算模式就是把計(jì)算分布到各個(gè)應(yīng)用當(dāng)中,規(guī)則服務(wù)器只負(fù)責(zé)規(guī)則的構(gòu)建、打包與測(cè)試,具體的規(guī)則計(jì)算發(fā)生在計(jì)算應(yīng)用當(dāng)中,規(guī)則服務(wù)器通過(guò)Http協(xié)議將知識(shí)包推送到各個(gè)計(jì)算應(yīng)用,分布式計(jì)算模式適用于單個(gè)服務(wù)器不強(qiáng),規(guī)則計(jì)算時(shí)需要的輸入數(shù)據(jù)結(jié)構(gòu)復(fù)雜的情況。
最后一種就是獨(dú)立服務(wù)模式,這種模式也是傳統(tǒng)規(guī)則引擎采用的模式,那就是規(guī)則服務(wù)器通過(guò)暴露Restful服務(wù)來(lái)接收各種類(lèi)型規(guī)則計(jì)算請(qǐng)求,請(qǐng)求把輸入數(shù)據(jù)以JSON格式提供,在一臺(tái)服務(wù)器上完成所有類(lèi)型的規(guī)則計(jì)算,計(jì)算完成后再把輸出數(shù)據(jù)以JSON格式返回, 在第22小節(jié)知識(shí)包Restful服務(wù)暴露與調(diào)用中詳細(xì)介紹了這種模式的配置及使用方式,本小節(jié)將只對(duì)嵌入模式和分布式計(jì)算模式兩種類(lèi)型結(jié)構(gòu)進(jìn)行介紹。
在之前介紹的內(nèi)容當(dāng)中,安裝與配置一節(jié)介紹的項(xiàng)目創(chuàng)建配置方式就是采用的嵌入模式,在嵌入式模式下URule Pro相關(guān)Jar包與業(yè)務(wù)應(yīng)用一起打包,作為一個(gè)應(yīng)用來(lái)進(jìn)行部署,這種模式結(jié)構(gòu)比較簡(jiǎn)單,開(kāi)發(fā)、部署起來(lái)都比較容易。
再來(lái)看看分布式計(jì)算模式示意圖:
在分布式計(jì)算模式下,包含URule Pro Console模塊的應(yīng)用被部署成一個(gè)獨(dú)立的Server,在這個(gè)Server上創(chuàng)建規(guī)則項(xiàng)目,在項(xiàng)目中根據(jù)業(yè)務(wù)需求添加決策集、決策表、交叉決策表、決策樹(shù)、評(píng)分卡、復(fù)雜評(píng)分卡、決策流等,再把這些文件打包到知識(shí)包中,最后通過(guò)HTTP協(xié)議暴露給各個(gè)客戶(hù)端業(yè)務(wù)系統(tǒng)使用。
分布式計(jì)算模式下客戶(hù)端獲取服務(wù)端知識(shí)包的方式:
在分布式計(jì)算模式下,URule Server上給客戶(hù)端提供的是若干個(gè)已經(jīng)構(gòu)建好的知識(shí)包對(duì)象,當(dāng)有客戶(hù)端需要進(jìn)行規(guī)則計(jì)算時(shí),它會(huì)檢查當(dāng)前客戶(hù)端中配置的“urule.knowledgeUpdateCycle”屬性值,如果為0,那么就直接請(qǐng)求URule Server獲取指知識(shí)包;如果為1,那么它會(huì)首先檢查客戶(hù)端本地緩存當(dāng)中是否存在指定的知識(shí)包,如果存在,就取本地緩存中的,如果不存在,則到URule Server下請(qǐng)求指定的知識(shí)包,然后將請(qǐng)求到的知識(shí)包緩存到客戶(hù)端內(nèi)存中,這樣下次就不再到URule Server上下載;如果“urule.knowledgeUpdateCycle”屬性值大于1,那么客戶(hù)端會(huì)首先檢查本地緩存中是否存在指定的知識(shí)包,如果存在,那么就拿當(dāng)前時(shí)間與本地緩存中的知識(shí)包的時(shí)間戳進(jìn)行比較,如果小于“urule.knowledgeUpdateCycle”屬性值,那么就直接取這個(gè)知識(shí)包,如果大于它,那么就到URule Server上通過(guò)時(shí)間戳檢查當(dāng)前知識(shí)包有沒(méi)有更新,如果有更新則取到客戶(hù)端,同時(shí)更新客戶(hù)端緩存里對(duì)應(yīng)的知識(shí)包;如果沒(méi)有更新,那么就直接采用當(dāng)前客戶(hù)端緩存里的知識(shí)包。。
搭建URule Server應(yīng)用的與安裝與配置一節(jié)中介紹的完全相同,就是在一個(gè)普通的java web應(yīng)用中將URule Pro Console模塊和URule Pro Core添加進(jìn)去。需要注意的是,在URule Server應(yīng)用搭建好了之后,要保證“/urule/loadknowledge”這個(gè)URL在可以匿名訪(fǎng)問(wèn),比如輸入類(lèi)似下面的地址,看看應(yīng)用會(huì)有什么樣的響應(yīng)。
在系統(tǒng)未登錄的情況下,訪(fǎng)問(wèn)上述URL看到的不是一個(gè)登錄頁(yè)面,那么就說(shuō)明“/urule/loadknowledge”這個(gè)URL在可以匿名訪(fǎng)問(wèn),是OK的。
如果出現(xiàn)我們應(yīng)用中的登錄界面之類(lèi),那就說(shuō)明“/urule/loadknowledge”這個(gè)URL被我們自己系統(tǒng)內(nèi)部的權(quán)限模塊給攔截了,需要我們?cè)谙到y(tǒng)中對(duì)內(nèi)部的權(quán)限進(jìn)行配置,使得“/urule/loadknowledge”URL在可以匿名訪(fǎng)問(wèn)。做好這個(gè)工作,那么URule Server的搭建工作就完成了,下面我們看看如果配置客戶(hù)端應(yīng)用。
配置客戶(hù)端應(yīng)用,首先要解決的是如果將URule Pro客戶(hù)端所需要的jar包添加到項(xiàng)目中,這里我們分maven項(xiàng)目以及非maven項(xiàng)目分別進(jìn)行討論。
如果當(dāng)前客戶(hù)端是基于maven的項(xiàng)目,那么我們需要在其pom.xml中添加以下依賴(lài):
<dependency>
<groupId>com.bstek.urule</groupId>
<artifactId>urule-core-pro</artifactId>
<version>2.2.3</version>
</dependency>
可以看到,在客戶(hù)端當(dāng)中就不再需要urule-console-pro模塊了,只需要一個(gè)urule-core-pro模塊即可。
上面的maven依賴(lài)中,我們使用的是2.2.3版本,實(shí)際使用時(shí),可以在網(wǎng)頁(yè)中打開(kāi)https://search.maven.org/,查詢(xún)“urule-core-pro”關(guān)鍵字,找到最新的urule-core-pro的版本信息,以確定在依賴(lài)中version位置要輸入的版本號(hào)信息。
到這里,pom的配置就完成了,我們?cè)賮?lái)看看一個(gè)標(biāo)準(zhǔn)的非maven的Web項(xiàng)目如何配置成URule Pro客戶(hù)端。
如果是一個(gè)非maven普通的java web項(xiàng)目,添加URule Pro客戶(hù)端就是將urule-core-pro的jar包及其依賴(lài)的第三方j(luò)ar包放到客戶(hù)端應(yīng)用的/WEB-INF/lib目錄下即可,urule-core-pro的jar包我們可以到https://search.maven.org/上下載最新的urule-core-pro-2.x的jar包,對(duì)于依賴(lài)的第三方j(luò)ar包,可以點(diǎn)擊此處下載。
URule Pro客戶(hù)端所需要的jar包添加到客戶(hù)端項(xiàng)目中后,接下來(lái)我們還需要加載urule-core-pro模塊中的spring配置文件。urule-core-pro模塊中的spring配置文件位于classpath根下,名為urule-core-context.xml。
如果我們的客戶(hù)端項(xiàng)目沒(méi)有采用spring框架,那么可以在web.xml中添加如下所示Listener來(lái)加載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>
如果我們的項(xiàng)目也采用了spring框架,那么只需要打開(kāi)項(xiàng)目中任意一個(gè)spring配置文件,在其中添加如下配置即可:
<import resource="classpath:urule-core-context.xml"/>
這樣urule-core-pro的spring配置文件的加載配置就完成了。
對(duì)于URule Pro客戶(hù)端應(yīng)用來(lái)說(shuō),在進(jìn)行規(guī)則計(jì)算時(shí),如果客戶(hù)端本地緩存沒(méi)有相應(yīng)的知識(shí)包,那么它會(huì)到URule Server上請(qǐng)求對(duì)應(yīng)的知識(shí)包,要給URule Pro客戶(hù)端應(yīng)用配置對(duì)應(yīng)的URule Server地址,我們需要添加一個(gè)properties文件,比如在項(xiàng)目的WEB-INF目錄下新建一個(gè)名為configure的properties文件,然后在我們項(xiàng)目中任意一個(gè)spring配置文件中添加如下配置加載這個(gè)properties文件:
<bean parent="urule.props">
<property name="location">
<value>/WEB-INF/configure.properties</value>
</property>
</bean>
打開(kāi)這個(gè)configure.properties文件,在其中添加一個(gè)名為“urule.resporityServerUrl”屬性,比如 urule.resporityServerUrl=http://192.168.18.11:8080/urule-server , 就表明我們?yōu)楫?dāng)前URule客戶(hù)端應(yīng)用配置的URule Server為“http://192.168.18.11:8080/urule-server”,這樣在進(jìn)行規(guī)則計(jì)算時(shí),如果客戶(hù)端本地緩存沒(méi)有相應(yīng)的知識(shí)包,那么它會(huì)到“http://192.168.18.11:8080/urule-server”上請(qǐng)求對(duì)應(yīng)的知識(shí)包。
從2.1.1版本開(kāi)始,urule-pro提供了動(dòng)態(tài)加載Jar包及Spring配置文件功能,具體見(jiàn)21.Spring Bean及Java類(lèi)的熱部署描述,如果我們使用的是urule-pro-2.1.1及以上版本,
那么在采用客戶(hù)端服務(wù)器模式配置應(yīng)用時(shí),客戶(hù)端配置了“urule.resporityServerUrl”屬性后,客戶(hù)端在啟動(dòng)時(shí)會(huì)自動(dòng)到服務(wù)端檢查是否有新的動(dòng)態(tài)Jar文件信息需要加載,如果有則下載到客戶(hù)端并加載,
所以這時(shí)服務(wù)端的“urule/dynamic/checkLatestJarsDir”和“urule/dynamic/loadDynamicJars”這兩個(gè)URL要保證匿名可訪(fǎng)問(wèn),否則客戶(hù)端啟動(dòng)時(shí)會(huì)產(chǎn)生錯(cuò)誤。
到這里,URule Pro客戶(hù)端的配置就全部完成了,通過(guò)指定urule.resporityServerUrl屬性值,我們的客戶(hù)端無(wú)論是標(biāo)準(zhǔn)的Java Web應(yīng)用還是普通的Java應(yīng)用,都可以與URule Server連接,從而在運(yùn)行時(shí)獲取到相應(yīng)的知識(shí)包。
但是,如果我們的客戶(hù)端應(yīng)用是標(biāo)準(zhǔn)的Java Web應(yīng)用,那么除了可以通過(guò)urule.resporityServerUrl屬性指定URule Server地址,從而主動(dòng)獲取知識(shí)包外,還可以通過(guò)配置一個(gè)Servlet被動(dòng)接收URule Server推送過(guò)來(lái)的知識(shí)包,這樣模式,相比主動(dòng)獲取知識(shí)包方式要高效的多,同時(shí)還可以時(shí)刻與Server上的知識(shí)包保持同步。
下面就來(lái)看看如何給一個(gè)類(lèi)型為標(biāo)準(zhǔn)Java Web應(yīng)用的客戶(hù)端配置接收服務(wù)端推送過(guò)來(lái)知識(shí)包的Servlet。
在之前內(nèi)容中我們就提過(guò),URule Pro的客戶(hù)端即可以是標(biāo)準(zhǔn)的Java Web應(yīng)用,也可以是普通的Java應(yīng)用。如果是普通Java應(yīng)用,那么上面的那么配置就可以了;如果是標(biāo)準(zhǔn)的Java Web應(yīng)用,那么我們還可以做些配置,使得其以主動(dòng)接收來(lái)自URule Server上推送過(guò)來(lái)的最新的知識(shí)包。
對(duì)于URule Server來(lái)說(shuō),如果在規(guī)則項(xiàng)目中配置了URule的客戶(hù)端地址,那么在知識(shí)包發(fā)布時(shí)會(huì)自動(dòng)推送到這些客戶(hù)端。所以我們的URule Pro客戶(hù)端如果是個(gè)標(biāo)準(zhǔn)的Java Web應(yīng)用,那么可以配置一個(gè)可以接收URule Server推送的知識(shí)包的Servlet。
打開(kāi)項(xiàng)目的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項(xiàng)的“/knowledgepackagereceiver”值是固定的,不能修改為其它值,否則將無(wú)法收到URule Server上推送過(guò)來(lái)的知識(shí)包。
同時(shí),客戶(hù)端中的這個(gè)用于接收知識(shí)包推送的Servlet還要保證其可以匿名訪(fǎng)問(wèn),也就是客戶(hù)端中如果被權(quán)限框架包裹,那么要保證“/knowledgepackagereceiver”這個(gè)URL在不登錄的情況下就可以訪(fǎng)問(wèn),
否則服務(wù)端將無(wú)法把知識(shí)包推送到目標(biāo)客戶(hù)端。
要實(shí)現(xiàn)推送功能,除了要配置對(duì)應(yīng)Java Web客戶(hù)端上的Servlet,還需要在URule Server上對(duì)可以接收推送的客戶(hù)端進(jìn)行定義。
打開(kāi)URule Pro的控制臺(tái),在規(guī)則項(xiàng)目中點(diǎn)擊右鍵,在彈出的菜單中選擇“配置接收推送客戶(hù)端”,就可以打開(kāi)客戶(hù)端配置頁(yè)面,如下圖:
我們可以添中多個(gè)客戶(hù)端,這樣在當(dāng)前項(xiàng)目發(fā)布知識(shí)包時(shí)就可以自動(dòng)推送到這里的客戶(hù)端上,如下圖:
配置完成后,點(diǎn)擊當(dāng)前項(xiàng)目的“知識(shí)包”節(jié)點(diǎn),選擇任意一個(gè)知識(shí)包,點(diǎn)擊工具欄上“發(fā)布當(dāng)前知識(shí)包”按鈕,可以看到有如下類(lèi)型的提示:
點(diǎn)擊“確定”,系統(tǒng)會(huì)嘗試向這些客戶(hù)端推送當(dāng)前發(fā)布的知識(shí)包對(duì)象,如果這些客戶(hù)端是存在的,就可以發(fā)布成功,這樣對(duì)應(yīng)的客戶(hù)端本地緩存中就會(huì)存儲(chǔ)這個(gè)發(fā)布的知識(shí)包對(duì)象。
前面我們介紹了在URule Pro客戶(hù)端中配置“urule.knowledgeUpdateCycle”屬性的含義及目的,一旦我們?cè)赨Rule Server中配置了客戶(hù)端地址,那么知識(shí)包每次發(fā)布都會(huì)被推送到這些客戶(hù)端。這樣在生產(chǎn)環(huán)境下,對(duì)于客戶(hù)端來(lái)說(shuō),“urule.knowledgeUpdateCycle”屬性值只要設(shè)置成1即可,也就是每次都在客戶(hù)端本地緩存中查找目標(biāo)知識(shí)包是否存在,如果存在直接使用。如果知識(shí)包有更新,URule Server會(huì)動(dòng)推送到目標(biāo)客戶(hù)端,對(duì)于客戶(hù)端來(lái)說(shuō)直接從本地緩存中就可以取到最新的知識(shí)包,這樣可以剔除所有不必要的客戶(hù)端與服務(wù)端的交互,節(jié)省網(wǎng)絡(luò)資源,同時(shí)可以大幅提高客戶(hù)端規(guī)則計(jì)算性能。
我們?cè)趯?duì)URule Pro進(jìn)行性能測(cè)試時(shí),一定要將“urule.knowledgeUpdateCycle”屬性值只要設(shè)置成1,因?yàn)椤皍rule.knowledgeUpdateCycle”屬性值默認(rèn)為0,所以每次執(zhí)行規(guī)則都會(huì)編譯一次規(guī)則包,這樣會(huì)帶來(lái)很差的測(cè)試結(jié)果,所以這點(diǎn)非常關(guān)鍵;
在客戶(hù)端中,將“urule.knowledgeUpdateCycle”設(shè)置成1后,檢驗(yàn)該屬性是否生效最好的方法是在客戶(hù)端調(diào)用服務(wù)端知識(shí)包時(shí)觀(guān)察控制臺(tái)是否有類(lèi)似“Load knowledgepackage [ packageId ] from remote...”這樣的字符輸出,如果有類(lèi)似輸出,則說(shuō)明urule.knowledgeUpdateCycle=1未生效,
我們需要進(jìn)一步檢查配置,找到未生效的原因。
同時(shí),名為"urule.debug"的屬性也會(huì)對(duì)性能產(chǎn)生一點(diǎn)影響,這個(gè)屬性值默認(rèn)為true,表示允許進(jìn)行調(diào)試信息輸出,這樣對(duì)于性能測(cè)試來(lái)說(shuō)無(wú)疑會(huì)造成影響,所以在性能測(cè)試或生產(chǎn)環(huán)境中建議將“urule.debug”屬性設(shè)置為false,這樣可以減少不必要的調(diào)試信息輸出,可顯著提升性能。
更多建議: