9

我将使用大学的图书馆系统来解释我的用例。学生在图书馆系统注册并提供他们的个人资料:性别,年龄,部门,以前完成的课程,当前注册的课程,已借书等。图书馆系统中的每本书都会根据学生的个人资料定义一些借阅规则,例如,计算机算法的教科书只能由在该班级注册的学生借阅;另一本教科书只能由数学系的学生借用;也可以规定学生最多只能借2本电脑网络书。由于借阅规则,当学生在图书馆系统中搜索/浏览时,他只会看到他可以借阅的书籍。所以,

以下是我使用 Drools 对设计的看法 - 每本书都有一个规则,其中学生档案的一些字段约束为 LHS,书籍规则的 RHS 只是将书籍 ID 添加到全局结果列表中,然后是所有书籍规则被加载到 RuleBase 中。当学生搜索/浏览图书馆系统时,会从 RuleBase 创建一个无状态会话,并将学生的个人资料断言为事实,然后学生可以借用的每本书都会触发其图书规则,您将获得完整的图书列表学生可以在全局结果列表中借用。

一些假设:图书馆将处理数百万本书;我不希望书本规则太复杂,平均每个规则最多3个简单的字段约束;系统需要处理的学生数量在100K左右,所以负载比较重。我的问题是:如果加载一百万本书规则,Drools 将占用多少内存?所有这百万条规则的触发速度有多快?如果 Drools 是合适的选择,我想听听经验丰富的用户在设计这样一个系统时的一些最佳实践。谢谢。

4

5 回答 5

11

首先,不要为每一本书制定规则。制定限制规则——定义的限制比书籍少得多。这将对运行时间和内存使用产生巨大影响。

通过规则引擎运行大量书籍将会很昂贵。特别是因为您不会向用户显示所有结果:每页只有 10-50 个。想到的一个想法是使用规则引擎来构建一组查询条件。(我实际上不会这样做——见下文。)

这是我的想法:

rule "Only two books for networking"
when
  Student($checkedOutBooks : checkedOutBooks),
  Book(subjects contains "networking", $book1 : id) from $checkedOutBooks,
  Book(subjects contains "networking", id != $book1) from $checkedOutBooks
then
  criteria.add("subject is not 'networking'", PRIORITY.LOW);
end

rule "Books allowed for course"
when
  $course : Course($textbooks : textbooks),
  Student(enrolledCourses contains $course)

  Book($book : id) from $textbooks,
then
  criteria.add("book_id = " + $book, PRIORITY.HIGH);
end

但我实际上不会那样做!

这就是我改变问题的方式:不向用户展示书籍是一种糟糕的体验。用户可能想要细读这些书籍以查看下次要获得哪些书籍。显示书籍,但不允许结帐受限制的书籍。这样,每个用户一次只能浏览 1-50 本书。这将是非常活泼的。上述规则将变为:

rule "Allowed for course"
   activation-group "Only one rule is fired"
   salience 10000
when
  // This book is about to be displayed on the page, hence inserted into working memory
  $book : Book(),

  $course : Course(textbooks contains $book),
  Student(enrolledCourses contains $course),
then
  //Do nothing, allow the book
end

rule "Only two books for networking"
   activation-group "Only one rule is fired"
   salience 100
when
  Student($checkedOutBooks : checkedOutBooks),
  Book(subjects contains "networking", $book1 : id) from $checkedOutBooks,
  Book(subjects contains "networking", id != $book1) from $checkedOutBooks,

  // This book is about to be displayed on the page, hence inserted into working memory.
  $book : Book(subjects contains "networking")
then
  disallowedForCheckout.put($book, "Cannot have more than two networking books");
end

我使用activation-group 来确保只触发一条规则,并使用salience 来确保它们按照我希望它们的顺序被触发。

最后,保持规则缓存。Drools 允许并建议您仅将规则加载到知识库中一次,然后从中创建会话。知识库很贵,会话很便宜。

于 2010-02-17T08:23:35.610 回答
7

我对 Drools(或一般的规则引擎)的经验是,如果用户对规则的可见性很重要,或者快速更改规则而不使其成为编码项目很重要,或者如果规则集很重要,那么它是一个很好的选择非常大,因此很难在代码中进行管理、思考和分析(因此您会让业务人员要求技术人员阅读代码并告诉他们在情况 X 中会发生什么)。

话虽如此,规则引擎可能是一个瓶颈。它们不会运行任何接近代码性能的东西,因此您确实需要在架构上预先管理它。在这种特定情况下,这背后肯定有一个数据库,您可以添加到性能问题,即数据库返回查询的速度比您在代码中分析整个集合的速度要快得多。

我绝对不会通过创建一百万个规则对象来实现这一点,而是我会创建一个可以分配多本书的书籍类型,并针对书籍类型运行规则,然后只显示允许类型的书籍。这样,您可以加载类型,将它们传递给规则引擎,然后将允许的类型推送到数据库端的查询中,该查询会拉取允许类型中的书籍列表。

类型变得有点复杂,因为实际上一本书可能有两种类型(如果您正在学习某门课程,或者通常如果您是该部门的一员,则允许),但该方法仍然应该成立.

于 2010-02-16T17:57:47.513 回答
1

我的问题是:如果加载一百万本书规则,Drools 将占用多少内存?所有这百万条规则的触发速度有多快?

你的电脑有多快,你有多少内存?从某种意义上说,您只能通过构建概念证明并用正确数量的(随机生成的)测试数据填充它来找出答案。我的经验是 Drools 比您预期的要快,并且您必须非常了解引擎盖下的内容才能预测什么会使其变慢。

请注意,您说的是一百万条规则会话事实(即 Book 对象),而不是一百万条规则。只有少数规则,不会花很长时间触发。可能较慢的部分是插入数百万个对象,因为 Drools 需要为每个新事实决定将哪些规则放在议程上。

遗憾的是,我们没有人对具有一百万个事实的特定设置有答案。

至于实现,我的方法是为学生想要签出的每本书插入一个 Book 对象,收回不允许的书,以及获取剩余(允许)Book 对象的查询,以及另一个查询获取原因列表。或者,使用具有可以在规则中设置的附加属性的boolean allowedRequestedBook对象。String reasonDisallowed

于 2010-08-26T11:17:16.787 回答
1

任何时候我们正在查看大型数据集(这个问题是关于...... Drools 是否适合大型数据集案例),请跳出框框思考(如下)。每当我们谈论“数百万个对象”或类似的 log-N 类型问题时,我认为它们所讨论的工具不一定是问题所在。所以是的,可以使用 Drools(或 JBoss 规则),但只有在特定的上下文中才有意义......

当您有任何东西的 log-N 时(针对输入交叉引用大型数据集),我建议使用更新颖的方法,例如数据库支持的 Bloom Filters。这些可以实现为 Java 对象,并由 Drools 引用以进行事实查找(但是那里的自定义编码)。

由于 Bloom Filter 是只有基本 insert()/contains() 函数的微小内存结构,它们确实有一个缺点……大约 1% 的误报率。所以这将用作主缓存。如果将 Drools 问题构建为通常为“否”作为答案,则 Bloom Filter 支持的事实表构造查找将非常快,并且内存占用很小(在我的实现中每条记录大约 1.1 个字节),因此 1 MB 的 RAM 用于这个案例。然后在“包含”的情况下(可能是误报),使用数据库支持的事实表来澄清。同样,如果在 80% 的时间里,查找是错误的,那么布隆过滤器将在内存和时间上节省大量成本。否则,纯(任何东西 - Drools 事实、数据库等)1M 记录查找每次都会非常昂贵(在内存和速度方面)。

于 2012-12-10T17:49:58.873 回答
-1

我会担心需要让规则的数量成为学生数量的函数——这真的会让事情变得棘手(这听起来像是最大的问题)。

于 2010-02-16T22:12:25.600 回答