ODM 到 Drools 的迁移:可以满足我的需求吗?

发布于 2025-01-17 15:38:59 字数 615 浏览 4 评论 0 原文

我正在研究 POC,看看我们是否可以从 ODM 迁移到 Drools,但我无法识别我们在 ODM 应用程序中使用的 Drools 中的某些功能。

示例:

  • 在 ODM 中,我们利用具有输入和输出的决策操作,该操作是从 Spring 应用程序调用的。此 ODM 操作调用复杂的规则流(父/子流),该规则流根据不同级别的元数据组织规则执行。如果满足条件,这些规则将构建一组输出数据,Spring 应用程序将使用这些数据根据结果进行不同的行为。请记住,决策操作会等待规则流完成,然后再使用该输出响应 Spring 应用程序。

在 Drools 中,我知道我可以构建一个 Spring Boot 应用程序并调用规则流,但规则流是异步的。 Drools 的行为与 ODM 不同,因此我似乎无法使用规则流。有多种选择可以等待并获取规则流的状态,但我们每天会收到数百万个请求,因此无法证明等待是合理的。我考虑过利用议程组/激活组来执行规则来控制我们的执行,但我们正在评估的数据很复杂,有大量的交叉数据验证,而且我们正在验证的数据(POJO)可能有 10 个级别深。是的,我们的结构非常庞大,可能有多达 500 多个规则。由于我们的复杂性,我只是看不到利用议程组/激活组来实现我们需要的东西。

有人对可能实现这种行为有任何想法吗?任何意见都表示赞赏:)

I'm working on a POC to see if we can migrate from ODM to Drools, but I'm not able to identify certain features within Drools that we utilize in our ODM apps.

Example:

  • In ODM we utilize a Decision Operation that has inputs and outputs, which is invoked from a Spring app. This ODM operation invokes a complex ruleflow (parent/sub flows), which organizes rule execution based on different levels of metadata. The rules, if condition is met, builds a set of output data that the Spring app uses to behave differently based on the result. Keep in mind the Decision Operation waits for the ruleflow to complete before responding back to the spring app with that output.

In Drools, I understand I can build a spring boot app and invoke a rule flow, but the rule flow is then async. Drools doesn't behave the same as ODM so doesn't appear I can use a rule flow. There are options to wait and get the state of the rule flow, but we receive millions of requests a day and can't justify putting in waits. I thought about executing rules utilizing agenda-group/activation-group to control our execution, but the data we are evaluating is complex, lots of cross data-validating, and the data we are validating (POJOs) can be 10 levels deep. Yes, our structure is massive and there can be up to 500+ rules. I just can't see utilizing agenda-group/activation-group to achieve what we need due to our complexity.

Would anyone have any thoughts on possibly achieving this type of behavior? Any input is appreciated :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

巷子口的你 2025-01-24 15:38:59

我对ODM一无所知,所以我无法评论相似性/差异。但是,从有关用例的问题中所描述的内容来看,我认为问题是您正在使用Drools错误。 :)

一般来说,我们会调用这样的规则:

KieContainer kieContainer = ...
KieBase rules = this.kieContainer.getKieBase("validation"); // call the validation rules
KieSession session = rules.newKieSession();
try {
    session.insert( ... ); // add facts into working memory
    session.fireAllRules();
} finally {
    session.dispose();
}

willeallrules 是一种同步的阻止方法。

另外,如果您想进行批处理处理,则会做类似的事情(例如,取自文档):

StatelessKieSession ksession = kbase.newStatelessKieSession();

List cmds = new ArrayList();
cmds.add( CommandFactory.newInsertObject( new Cheese( "stilton", 1), "stilton") );
cmds.add( CommandFactory.newStartProcess( "process cheeses" ) );
cmds.add( CommandFactory.newQuery( "cheeses" ) );
ExecutionResults bresults = ksession.execute( CommandFactory.newBatchExecution( cmds ) );
Cheese stilton = ( Cheese ) bresults.getValue( "stilton" );
QueryResults qresults = ( QueryResults ) bresults.getValue( "cheeses" );

请注意,我们在命令列表中调用 startProcess ,但不是直接。此外,我们仍然在 execute 呼叫上等待结果,因此, startProcess 确实会异步进行,但我们仍然阻止所有执行措施完成,然后继续在 ececute ececute


您所陈述的用例是:

规则,如果满足条件,则构建了一组春季应用程序根据结果行为不同的输出数据。

这里没有什么可以阻止您使用流口水。在我以前的公司中,我们有一组规则,这些规则实际上根据请求中的数据状态在服务之间进行了路由,包括修改飞行中的请求。我们还制定了可以进行正常处理的规则,例如验证,计算等。

您的模型深度也不是真正的障碍 - 无论其结构如何,您都可以针对模型编写规则。有些类型本质上是较低的(请不要将 MAP s传递到规则中),但通常,如果它在工作内存中,则可以使用它。

最后,处理时间主要是您的规则书写效果的一个因素。流口水中有一些结构可以使您修改工作记忆并重新运行规则 - 这会导致他们花更多的时间,因为(duh)您第二次运行规则!但是,一个简单的秋季规则 - 触发哪些触发并继续移动的规则 - 这些规则可能非常快。在我的最后一份工作中,我提供了一项服务,其中有140万条规则,该规则具有SUESCOND SLA。之所以如此之快,是因为没有“更新”电话,并且没有关心其他规则的规则。规则有效地无状态,最差的性能为300毫秒(平均为30毫秒;这是整个Spring-Boot应用程序的往返,而不仅仅是实际规则评估。)


对于依赖复杂数据对象的规则,POJO中的许多级别,您将如何得出该数据而不导致规则关心其他规则?假设我的对象结构就像人一样 - >车辆 - >制作 - >型号 - >选项。如果我在“选项”上专门运行规则,则如何在选项规则中获取“模型”数据?如果模型或制造为空/空,以阻止运行的选项怎么办?

解析示例,我们有这些模型(在所有字段上假设Getters and Setter):

class Options {}
class Model {
  private Options options;
}
class Make {
  private Model model;
}
class Vehicle {
  private Make make;
}
class Person {
  private Vehicle vehicle;
}

要到达“选项”,我们只需将它们从中间模型中抽出即可。假设您将 Person 实例放入工作记忆中:

rule "Options"
when
  // this is the Person in working memory; get the vehicle out.
  Person( $v: vehicle )

  // then drill down to Options by repeating the process
  Vehicle( $make: make ) from $v
  Make( $model: model ) from $make
  Model( $opts: options ) from $model

  // now we can do stuff with $opts
then
  // $opts is available for use here too
end

流口水通常非常擅长防御性“ Got”,但是您可以通过添加空检查来自行防御。例如:

rule "Options with explicit null checks"
when
  Person( $v: vehicle != null )
  Vehicle( $make: make != null ) from $v
  Make( $model: model != null ) from $make
  Model( $opts: options != null ) from $model
then
  // ...
end

或者,如果您想快速失败,并且只需丢弃带有不良数据的输入,则可以从工作内存中缩回它们。这是潜在危险的,因为它是从工作流程中过早退出,如果您不知道它在那里,可能会导致下游潜在的错误。 (这有点类似于Java代码中有多个“返回”陈述;如果您要调试方法底部附近,并且不知道早期返回更远,这可能会导致您浪费时间或 行为。

rule "Retract incomplete date"
salience 100
when
  $person: Person ($v: vehicle != null)

  // as an example, this rule is going to trap for missing Make
  Vehicle( make == null ) from $v
then
  retract($person);
end

引入意外 更长的火。

显着性并不是必需的,但是从历史上看,我发现当他们明确地称其为比常规规则的早期出现时,可以在精神上跟踪这样的早期回缩。总的来说,简单地编写相互排斥的规则是更好的做法,但是您可能会发现使用早期缩回的性能略有差异。

I don't know anything about ODM, so I can't comment about the similarities/differences. But from what is described in the question about the use case, I think the problem is that you're using Drools wrong. :)

Generally speaking, we'd invoke rules like this:

KieContainer kieContainer = ...
KieBase rules = this.kieContainer.getKieBase("validation"); // call the validation rules
KieSession session = rules.newKieSession();
try {
    session.insert( ... ); // add facts into working memory
    session.fireAllRules();
} finally {
    session.dispose();
}

fireAllRules is a synchronous, blocking method.

Alternatively, if you want to do batch processing, you'd do something like this (example taken from the documentation):

StatelessKieSession ksession = kbase.newStatelessKieSession();

List cmds = new ArrayList();
cmds.add( CommandFactory.newInsertObject( new Cheese( "stilton", 1), "stilton") );
cmds.add( CommandFactory.newStartProcess( "process cheeses" ) );
cmds.add( CommandFactory.newQuery( "cheeses" ) );
ExecutionResults bresults = ksession.execute( CommandFactory.newBatchExecution( cmds ) );
Cheese stilton = ( Cheese ) bresults.getValue( "stilton" );
QueryResults qresults = ( QueryResults ) bresults.getValue( "cheeses" );

Notice we call startProcess in the list of commands, but not directly. Further we still wait for the results at the execute call, so while startProcess does proceed asynchronously, we still block for all executions to complete before continuing at execute.


Your stated use case was:

The rules, if condition is met, builds a set of output data that the Spring app uses to behave differently based on the result.

There's nothing here that precludes you from using Drools. At my previous company, we had a set of rules that actually routed requests between services based on the state of the data in the request, including modifying the request in flight. We also had rules that could do normal processing like validation, calculation, and so on.

Your model depth is also not really a hindrance -- you can write rules against your model no matter how it's structured. There are some types which are inherently inferior (please don't pass Maps into the rules) but generally if it's in working memory you can work with it.

Finally, processing time is a factor mostly of how well written your rules are. There are structures in Drools that allow you to modify working memory and rerun the rules -- this will cause them to take inherently more time because (duh) you're running the rules a second time! But a simple fall-through sort of rules -- trigger which ever ones trigger and keep moving -- those can be very fast. At my last job I had a single service with 1.4 million rules that had a sub-second SLA; it was so fast because there were no 'update' calls, and none of the rules cared about which of the other rules also fired. The rules were effectively stateless, and the worst-case performance was 300 milliseconds (average was 30 ms; and that's round trip through the entire spring-boot app and not just the actual rule evaluation.)


For rules that depend on complex data objects many levels deep in a POJO, how would you derive that data and not causing rules to care about other rules? Let's say my object structure is something like Person -> Vehicle -> Make -> Model -> Options. If I'm running rules specifically on "Options", how are getting to the "model" data in the Options rules? What if model or make is empty/null to block Options from running?

Parsing out the example, we have these models (assume getters and setters on all fields):

class Options {}
class Model {
  private Options options;
}
class Make {
  private Model model;
}
class Vehicle {
  private Make make;
}
class Person {
  private Vehicle vehicle;
}

To get to the 'options', we just pull them out of the intermediate models. Assuming you put a Person instance into working memory:

rule "Options"
when
  // this is the Person in working memory; get the vehicle out.
  Person( $v: vehicle )

  // then drill down to Options by repeating the process
  Vehicle( $make: make ) from $v
  Make( $model: model ) from $make
  Model( $opts: options ) from $model

  // now we can do stuff with $opts
then
  // $opts is available for use here too
end

Drools is generally pretty good at doing defensive 'gets', but you can be defensive in your own right by adding a null check. For example:

rule "Options with explicit null checks"
when
  Person( $v: vehicle != null )
  Vehicle( $make: make != null ) from $v
  Make( $model: model != null ) from $make
  Model( $opts: options != null ) from $model
then
  // ...
end

Alternatively if you want to fail fast and just discard any inputs with bad data, you can retract them from working memory. This is potentially dangerous because it's a premature exit from the workflow, and can cause potential bugs downstream if you don't realize it's there. (It's somewhat analogous to having multiple "return" statements in your Java code; if you're debugging down near the bottom of a method and aren't aware that there's an early return much farther up, that might cause you to waste time or introduce unexpected behavior.)

rule "Retract incomplete date"
salience 100
when
  $person: Person ($v: vehicle != null)

  // as an example, this rule is going to trap for missing Make
  Vehicle( make == null ) from $v
then
  retract($person);
end

Word of caution: once you call retract, that item is gone from working memory, so if any subsequent rules were relying on it, they'll no longer fire.

The salience isn't necessary but historically I've found it easier to mentally track early retractions like this when they're explicitly called out as happening earlier than the regular rules. Generally speaking it's better practice to simply write rules that are mutually exclusive, but you may find marginally better performance using an early retract.

埋葬我深情 2025-01-24 15:38:59

在流口水中,我知道我可以构建一个弹簧启动应用程序并调用规则流,但是规则流是异步的。流口水与ODM的行为不一样,因此我可以使用规则流。

流口水中有相同类型的ODM RuleFlow功能。它不太复杂,但您可以达到相同的结果,即以下结果:

  • 将您的决策组织成较小的规则序列
  • ,因为这些不同的任务/集合以执行决策编排,

请参见

org/drools/preasure/7.67.0.final/drools-docs/html_single/#_ ch.taskAssigning“ rel =“ nofollow noreferrer”>“ nofollow noreferrer”> ruleflow :

  • 直接在JSON/XML中的Kieserver(规则执行服务器/HTDS的Drools概念)中直接作为Web服务(您需要首先安装Kieserver)。
  • 从一个针对规则中的对象导航的Java客户端来称为Kieserver

,规则创作是相同的,主要区别是DRL langage。

最好的
伊曼纽尔

in Drools, I understand I can build a spring boot app and invoke a rule flow, but the rule flow is then async. Drools doesn't behave the same as ODM so doesn't appear I can use a rule flow.

There is the same type of ODM ruleflow features in Drools. It is less sophisticated but you can achieve the same result which is :

  • organise your decision into smaller sets of rules
  • sequence as a flow these differents tasks/sets to perform a decision orchestration

see Ruleflow examples in Drools doc 7.67

Just like in ODM , you can call this ruleflow :

  • directly as a web service in the Kieserver (drools concept for Rule Execution Server/HTDS) in JSON/XML (you need to install kieserver first).
  • from a Java client that calls the kieserver

Regarding object navigation in rules, rule authoring is the same , the main difference is the DRL langage.

Best
Emmanuel

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文