使用Drools和无服务器实现业务规则编排


业务规则引擎(BRE)在企业中被用来管理关键业务的决策。用于做出这种决定的逻辑或规则的复杂程度可能不同。
一个财务部门可能有一个基本的规则,让任何超过一定金额的购买都要得到董事的批准。
一家抵押贷款公司可能需要根据输入(例如,信用评分、债务收入比、首付)运行复杂的规则,以做出贷款的批准决定。

将这些规则与应用逻辑解耦,为你的规则管理提供了敏捷性,因为业务规则可能经常改变,而你的应用可能不会。它还可以提供整个企业的标准化,所以每个部门都可以用相同的分类法进行沟通。

许多商业规则引擎作为BPMS产品的一部分,为规则执行提供协调能力。为了使用开源规则引擎管理系统成功迁移到云端,你需要协调能力来管理传入的规则请求、审计规则和跟踪异常。

这篇文章展示了一个协调框架,允许你使用一个开源规则引擎。
它使用Drools规则引擎建立了一套规则,用于根据Car和Person对象的属性来计算保险费。
这使用AWS Step Functions、AWS Lambda、Amazon API Gateway、Amazon DynamoDB和开源的Drools规则引擎来展示。
你可以交换规则引擎,只要你能在AWS云环境中管理它,并把它作为一个API公开。

架构:

  • API网关--一种完全管理的服务,使API消费者更容易创建、发布、维护、监控和保护任何规模的API。API网关帮助你管理到后端系统的流量,在这种情况下是Step Functions,它协调了任务的执行。对于REST API的使用情况,你也可以为你的API数据设置一个具有可定制的密钥和秒级生存时间的缓存,以避免每次请求都会冲击你的后端服务。
  • Step Functions - 一个低代码服务,协调完成任务所涉及的多个步骤。步骤函数使用有限状态机(FSM)模型,它使用给定的状态和转换来完成任务。该图描述了三种状态。审计请求、执行规则集和审计响应。我们按顺序执行它们。你可以添加额外的状态和转换,比如验证传入的有效载荷,以及分支平行执行的状态。
  • Drools规则引擎Spring Boot应用--规则执行的运行时组件。你将Drools规则引擎Spring Boot应用程序设置为Apache Maven Docker项目,并带有Drools Maven依赖。然后你将Drools规则引擎Docker镜像部署到亚马逊弹性容器注册中心(Amazon ECR),创建一个AWS Fargate集群,以及一个亚马逊弹性容器服务(Amazon ECS)服务。该服务启动亚马逊ECS任务并维护所需的计数。应用程序负载平衡器将流量均匀地分配给所有运行的容器。
  • Lambda - 一个无服务器的执行环境,给你一个与Drools引擎互动的能力和一个用于规则执行审计功能的持久层。Lambda组件提供了在DynamoDB中持久化传入请求和传出响应所需的审计功能。除了审计功能外,Lambda还用于调用Drools Spring Boot应用程序所暴露的服务。
  • DynamoDB--一个完全可管理的、高度可扩展的键/值存储,用于保存规则执行信息,如请求和响应的有效载荷信息。DynamoDB为传入的请求JSON有效载荷和传出的响应JSON有效载荷提供持久化层。审计Lambda函数在收到步骤函数的请求或响应事件时,会调用DynamoDB的put_item()方法。DynamoDB表rule_execution_audit有一个条目,用于与由应用程序(上游)发起的传入请求-ID相关的每个请求和响应。

Drools规则引擎的实现
Drools规则引擎将业务规则与业务流程分开。你使用DRL(Drools规则语言),将业务规则定义为.drl文本文件。你定义模型对象来构建规则。

模型对象是使用Eclipse定义的POJO(Plain Old Java Objects),并安装了Drools插件。你应该对构建规则和使用Drools规则引擎执行规则有一定程度的了解。

你在作为GitHub repo一部分的.drl文件中定义以下规则。这些规则的目的是根据作为输入的模型对象来评估司机的保险费。输入是汽车和司机对象,输出是保单对象,保单对象根据规则中定义的某些标准计算保费。

rule "High Risk"
     when     
         $car : Car(style ==
"SPORTS", color == "RED"
         $policy : Policy() 
         and $driver : Driver ( age < 21 )                             
     then
         System.out.println(drools.getRule().getName() +
": rule fired");          
         modify ($policy) { setPremium(increasePremiumRate($policy, 20)) };
 end
 
 rule
"Med Risk"
     when     
         $car : Car(style ==
"SPORTS", color == "RED"
         $policy : Policy() 
         and $driver : Driver ( age > 21 )                             
     then
         System.out.println(drools.getRule().getName() +
": rule fired");          
         modify ($policy) { setPremium(increasePremiumRate($policy, 10)) };
 end
 
 
 function double increasePremiumRate(Policy pol, double percentage) {
     return (pol.getPremium() + pol.getPremium() * percentage / 100);
 }

一旦定义了规则,你就定义一个RestController,它接受输入参数并评估上述规则。下面的代码片段是控制器中定义的POST方法,它处理请求并将响应发送给调用者。

@PostMapping(value ="/policy/premium", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE }, produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
    public ResponseEntity<Policy> getPremium(@RequestBody InsuranceRequest requestObj) {
        
        System.out.println(
"handling request...");
        
        Car carObj = requestObj.getCar();        
        Car carObj1 = new Car(carObj.getMake(),carObj.getModel(),carObj.getYear(), carObj.getStyle(), carObj.getColor());
        System.out.println(
"##########CAR##########");
        System.out.println(carObj1.toString());
        
        System.out.println(
"##########POLICY##########");        
        Policy policyObj = requestObj.getPolicy();
        Policy policyObj1 = new Policy(policyObj.getId(), policyObj.getPremium());
        System.out.println(policyObj1.toString());
            
        System.out.println(
"##########DRIVER##########");    
        Driver driverObj = requestObj.getDriver();
        Driver driverObj1 = new Driver( driverObj.getAge(), driverObj.getName());
        System.out.println(driverObj1.toString());
        
        KieSession kieSession = kieContainer.newKieSession();
        kieSession.insert(carObj1);      
        kieSession.insert(policyObj1); 
        kieSession.insert(driverObj1);         
        kieSession.fireAllRules(); 
        printFactsMessage(kieSession);
        kieSession.dispose();
    
        
        return ResponseEntity.ok(policyObj1);
    }    

详细点击标题