成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

轉轉圖書對基于Drools引擎的DMN實踐

開發 架構
DMN主要應用在向程序員以外的人員提供決策管理的能力,以求更準確地反映目的,從程序員的角度講可能和寫ifelse沒什么不一樣,但是其他角色的參與人員可以通過較低的學習成本來上手實現規則,能夠減少溝通成本和不同人的理解差異產生的不符合預期的結果。

1 背景介紹

1.1 DMN是什么

DMN全稱Decision Model and Notation(決策模型和符號、決策模型和表示法),是一種用于表示業務決策和規則的規范,旨在幫助參與決策的人都能簡單快速理解決策過程。

圖片

DMN logo

DMN是由OMG(Object Management Group,對象管理組織)管理的一種規范,該組織下比較知名的還有UML等。

圖片

DMN示例

如圖所示,DMN的表現形式近似于流程圖,通過可視化來更直觀地體現出流轉和處理的過程,而各個節點使用附帶邏輯的表格來表現該節點處理數據的方式。

由于DMN是一個規范,所以在應用上,主要依靠各個DMN工具供應商提供具體實現,近似于SQL語句和MySQL、Oracle的關系。

1.2 為什么要用DMN

應用DMN主要目的是為了解決轉轉圖書項目定價邏輯過于復雜的問題。

在引入DMN之前,圖書項目使用java代碼實現產品人員提供的定價邏輯。但是隨著邏輯越來越復雜,定價邏輯的代碼也越來越難以閱讀和維護。同時,將產品人員的邏輯翻譯成代碼是一個單向過程,只有程序員能理解實現過程,產品人員只能通過結果反推是否正確合理,在邏輯變得復雜之后,很難快速發現問題。

圖片

復雜規則的一部分,區間和系數

而通過DMN,可以可視化的表示出邏輯過程,產品人員也可以直觀的看到是否符合預期,還能夠進行編輯,從而解決了只有程序員掌握實現而過于依賴程序員的問題,也能減少表述交流的過程產生理解偏差進而導致的錯誤。

圖片

使用DMN實現的規則表現

1.3 什么是Drools

Drools是用java語言編寫的開源規則引擎,是DMN規范的一種實現。舉例來說DMN規范就是接口,Drools就是實現了接口的其中一個工具類。

圖片

Drools logo

Drools屬于Kie開源社區,而kie社區由Red Hat贊助,有比較高的社區活躍度。

圖片

Kie旗下的產品

1.4 為什么選擇Drools

Drools引擎是基于java實現的,這使得不需要為Drools單獨部署運行環境,運維成本是0,十分友好。

其次,DMN規范規定實現其規范的軟件必須滿足三級遞增的符合性級別,三級最高,一級最低,滿足三級級別時必須同時滿足一級和二級級別。而Drools引擎對DMN規范的支持屬于三級級別,功能完善。

圖片

Drools引擎對DMN各個版本提供支持

同時,Drools引擎社區活躍度高,同時提供了完整的工作組件,可靠性高。

2 Drools引擎應用

以下內容基于7.61.0版本,與8.x及以上的版本存在差異

2.1 官方推薦的最直接的應用方式

首先需要部署運行一個Kie Server用來執行DMN規則,然后部署Drools官方提供的基于Web的工作站軟件用來編輯、測試、發布DMN規則。

圖片

Drools提供的工作站軟件

當部署完成DMN規則之后,可以通過Kie Server REST API來運行規則獲取結果,即通過Http的方式請求Kie Server提供的接口。

2.2 轉轉圖書的限制

首先說圖書項目并沒有直接按照官方推薦的做法部署應用,原因有幾個方面:

第一點,轉轉內部項目部署運行有自有的框架體系,而Kie Server是基于JBoss運行的服務器軟件,在現有體系中部署一個外部項目需要額外的運維成本。

其次,Kie Server作為一個第三方工具,當出現問題時僅靠圖書項目的人員難以解決,而等待社區反饋對于轉轉圖書這種線上的商業項目難以接收。所以為了盡可能的減少出現問題的概率,節約人力,圖書項目傾向于盡可能少的引入外部依賴。

基于以上原因,圖書項目在應用Drools的時候選擇了另外一種方式。

3 脫離Kie Server的Drools引擎實踐

脫離開Kie Server,自然就沒有了REST API的http接口,同時也失去了官方工作站的支持,但是相對的,Drools提供了一些對這種場景下的支持。

3.1 在線編輯DMN規則

在Kie旗下有另一款名為Kogito的產品,是一個提供在線編輯BPMN和DMN的服務器軟件,同時其中有一個all-in-one的js文件,實現了在線編輯DMN的全部功能。

圖片

js提供的接口

圖書項目基于這個js文件進行了包裝,增加易用性,使得DMN編輯功能融入到現有的工作后臺之中。

圖片

包裝頁面,下方是js提供的功能區

同時增加編輯記錄列表用來便于管理和回滾。

圖片

編輯列表

js工具編輯后的DMN規則內容是xml格式的字符串,可以使用js提供的getContent()接口導出。

3.2 使用Drools引擎執行DMN規則

沒有了Kie Server的支持之后,需要通過代碼的方式運行Drools引擎。

首先在項目中引入Drools引擎的組件

圖片

引入Drools引擎組件

然后在項目中創建Drools引擎的引用并執行。

// 初始化KieServices
KieServices kieServices = KieServices.Factory.get();
// 通過指定的maven依賴創建Kie容器
ReleaseId releaseId = kieServices.newReleaseId( "com", "my-kjar", "1.0.0" );
KieContainer kieContainer = kieServices.newKieContainer( releaseId );
// 通過容器獲取DMN運行時
DMNRuntime dmnRuntime = KieRuntimeFactory.of(kieContainer.getKieBase()).get(DMNRuntime.class);
// 通過DMN運行時獲取需要執行的DMNModel,其中包含了DMN規則
String namespace = "my-namespace";
String modelName = "dmn-model-name";
DMNModel dmnModel = dmnRuntime.getModel(namespace, modelName);
// 獲取上下文,并傳入DMN規則需要用到的數據
DMNContext dmnContext = dmnRuntime.newContext();
dmnContext.set("inputData", "123");
// 執行規則獲取結果
DMNResult dmnResult = dmnRuntime.evaluateAll(dmnModel, dmnContext);
for (DMNDecisionResult dr : dmnResult.getDecisionResults()) {
log.info("Decision: '" + dr.getDecisionName() + "', " + "Result: " + dr.getResult());
}

由于Kie容器使用maven作為讀取DMN配置的手段,所以要求DMN規則內容需要打包到Kie容器能夠識別的jar包里,并且部署到項目可訪問的maven環境中。

3.3 完善處理流程

按照上述流程就可以實現脫離Kie server運行Drools引擎。但是距離落地上線還有一小點距離。

官方的工作站可以提供DMN規則上線前的驗證和測試功能,但是all-in-one的js文件沒有,所以為了保證準確性和穩定性,需要額外實現DMN規則的驗證動作。

這里可以使用KieContainer提供的verify接口來觸發Drools引擎的驗證動作并獲取結果。

Results verify = kieContainer.verify();
for (Message message : verify.getMessages()) {
log.info(message.getLevel().name() + ": " + message.getText());
}

將驗證流程放到保存DMN規則的時候,就可以快速發現是否存在編寫錯誤。

3.4 DLC - 脫離maven環境運行Drools引擎

前面說了Drools引擎需要使用maven獲取運行的DMNjar文件,但是在實際應用中,線上環境不一定會部署maven。例如圖書項目需要在公司內部公用的spark集群上運行Drools,但是spark集群上沒有部署maven環境,按照上述流程運行就會報錯。

所以需要一個能夠使Drools脫離maven環境的手段。

通過分析源碼可以發現,在創建KieContainer的時候,會使用KieServices.getRepository()方法獲取數據源,并通過maven坐標查找其中的KieModule。所以需要做的就是直接我們需要的jar寫入KieServices的數據源中:

// 首先通過JarOutputStream生成包含DMN規則字符串,且符合Drools規范的jar二進制流
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
JarOutputStream jos = new JarOutputStream(outputStream);
// kmodule.xml
jos.putNextEntry(new JarEntry("/META-INF/kmodule.xml"));
jos.write("<?xml versinotallow=\"1.0\" encoding=\"UTF-8\"?><kmodule xmlns=\"http://www.drools.org/xsd/kmodule\"><kbase name=\"kbase_1\" packages=\"rules\" default=\"true\"><ksession name=\"ksession_1\" default=\"true\"/></kbase></kmodule>".getBytes(StandardCharsets.UTF_8));
// pom.properties
jos.putNextEntry(new JarEntry("/META-INF/maven/com.myspace/test/pom.properties"));
jos.write("groupId=com.myspace\nartifactId=test\nversinotallow=1.0.0".getBytes(StandardCharsets.UTF_8));
// pom.xml
jos.putNextEntry(new JarEntry("/META-INF/maven/com.myspace/test/pom.xml"));
jos.write("<?xml versinotallow=\"1.0\" encoding=\"UTF-8\"?><project xsi:schemaLocatinotallow=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\" xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> <modelVersion>4.0.0</modelVersion> <groupId>com.myspace</groupId> <artifactId>test</artifactId> <version>1.0.0</version> <packaging>kjar</packaging> <name>test</name> <description></description></project>".getBytes(StandardCharsets.UTF_8));
// dmn
jos.putNextEntry(new JarEntry("/config/rules/test.dmn"));
jos.write(dmn.getBytes(StandardCharsets.UTF_8));
jos.finish();
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
// 初始化KieServices
KieServices kieServices = KieServices.Factory.get();
// 獲取KieServices的數據源
KieRepository repository = kieServices.getRepository();
// 向數據源中加入基于生成二進制流構造的KeiModule
KieModule kieModule = repository.addKieModule(kieServices.getResources().newInputStreamResource(inputStream));

如上就可以實現在沒有maven環境的時候仍然能夠讓KieServices獲取到我們需要DMN規則。

但是僅僅如此還不夠,在創建KieContainer的時候,內部會生成一個KieProject實例,KieProject在實例化的過程中會默認生成一個基于maven的MavenClassLoaderResolver用于查找jar,而缺少maven環境的情況下在生成MavenClassLoaderResolver的時候也會報錯。為此,我們需要一個取代MavenClassLoaderResolver的辦法。

通過分析Drools源碼可以發現,在源碼中,某些時候會使用ProjectClassLoader.findParentClassLoader()來獲取基于當前運行環境的ClassLoader。

所以,需要在創建KieContainer的時候使用ProjectClassLoader.findParentClassLoader()生成的ClassLoader來取代默認的MavenClassLoaderResolver:

// 使用另外一個接收ClassLoader的接口來生成KieContainer
KieContainer kieContainer = kieServices.newKieContainer(kieModule.getReleaseId(), ProjectClassLoader.findParentClassLoader());

如此一來,就可以完全脫離maven環境來使用Drools引擎了,而Drools引擎也可以融入到任意的java項目之中,部署到任意的java環境之下。

4 總結

DMN在實際應用中有比較明顯的優點:

  • 可以在不修改代碼的情況下更新邏輯,減少上線過程中可能產生的問題
  • 可以通過一套代碼實現各種場景的需求
  • 流程可視化,便于理解邏輯的運行
  • 能夠讓一部分不熟悉程序代碼的人員也可以參與編輯,避免流程全部只由程序員了解

但是相對的也存在一些弊端或者表現不夠好的地方:

  • 流程復雜時圖形化表現比較雜亂,尤其是多個決策節點依賴相同的上游時
  • 編輯規則時還是會有一部分場景條件需要寫代碼才能實現,例如列表包含(可以使用DMN專用代碼FEEL實現,或者引用已經實現的java方法實現)
  • 運行規則的時間相較于使用java代碼實現要慢,因為中間涉及規則文件解析和各個節點的計算,而java代碼可以更直接的實現

圖片

復雜規則示例

總體而言,DMN主要應用在向程序員以外的人員提供決策管理的能力,以求更準確地反映目的,從程序員的角度講可能和寫ifelse沒什么不一樣,但是其他角色的參與人員可以通過較低的學習成本來上手實現規則,能夠減少溝通成本和不同人的理解差異產生的不符合預期的結果。

5 參考資料

Drools官方網站:https://www.drools.org/

Drools官方的DMN教學:https://www.drools.org/learn/dmn.html

Drools官方的15分鐘簡易教學:https://learn-dmn-in-15-minutes.com/learn/introduction

Kogito在線編輯網頁:https://sandbox.kie.org/#/

Kie官方網站:https://www.kie.org/

OMG官方網站的DMN頁:https://www.omg.org/dmn/

作者簡介

項贏,轉轉資深java工程師。長期服務于轉轉圖書項目。

責任編輯:武曉燕 來源: 轉轉技術
相關推薦

2023-06-07 08:32:32

引擎技術while

2024-07-31 20:45:45

2023-10-16 17:41:40

Drools

2023-07-12 08:33:34

引擎LiteFlow編排

2023-11-01 07:44:29

轉轉Flutter業務

2022-11-07 14:45:26

轉轉價格DDD

2023-12-27 19:12:42

OLAP自助分析

2023-03-22 08:32:35

2023-03-02 08:54:32

2022-10-28 09:15:02

2022-10-28 08:31:43

2023-03-02 08:32:41

2023-02-08 09:42:30

策略方式容量

2022-12-15 08:35:01

用戶畫像平臺

2024-06-06 08:18:42

回收業務

2023-04-19 13:18:41

動態線程池平臺

2024-07-18 08:40:28

2024-11-25 08:20:22

2023-01-04 08:31:10

轉轉測試環境

2024-09-11 19:36:24

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 成人福利在线视频 | 亚洲欧美日韩精品久久亚洲区 | 精品欧美在线观看 | 精品一区二区三区在线观看 | 日韩免费视频一区二区 | 一级片av| 久久久久久久av | 最新国产精品视频 | 亚洲国产精品久久 | 天天干天天想 | 国产日韩欧美精品一区二区三区 | 色视频在线播放 | 黄色大片视频 | www.一区二区三区.com | 成人精品国产一区二区4080 | 在线观看亚洲精品 | 三级黄色片在线播放 | 亚洲国产精品suv | 成人久久久 | 精品久久一区 | 亚洲网站观看 | 日韩不卡一区二区 | 午夜精品久久久久久久久久久久久 | 91精品综合久久久久久五月天 | 国产精品高潮呻吟久久 | 毛片一区二区三区 | 希岛爱理在线 | 精品一区二区三区免费视频 | 免费在线观看av片 | 毛片一区二区三区 | 久久精品99 | 九九在线视频 | av在线一区二区三区 | 亚洲精品国产偷自在线观看 | 福利视频亚洲 | 四虎最新地址 | 91精品免费 | 麻豆changesxxx国产 | 依人成人 | 日韩乱码在线 | 极品粉嫩国产48尤物在线播放 |