我将使用大学的图书馆系统来解释我的用例.学生注册库中的系统,并提供他们的个人资料:性别,年龄,部门,之前完成的课程,目前注册的课程,书籍已经借等,每本书在图书馆系统将定义基于学生的个人资料中的借贷规则,例如,计算机算法的教科书只能由目前在该课程注册的学生借用; 另一本教科书只能由数学系的学生借用; 也可能有规则,学生最多只能借2本电脑网络书.由于借用规则,当学生在图书馆系统中搜索/浏览时,他只会看到可以借用的书籍.因此,该要求实际上归结为有效生成学生有资格借阅的书籍清单.
以下是我使用Drools对设计进行设想的方法 - 每本书都有一个规则,对学生档案有一些字段限制作为LHS,书规则的RHS只是将书籍ID添加到全局结果列表,然后是所有书籍规则被加载到RuleBase中.当学生搜索/浏览图书馆系统时,会从RuleBase创建无状态会话,并且学生的个人资料被确认为事实,然后学生可以借用的每本书都会触发其图书规则并获得完整的图书清单.学生可以在全球结果列表中借阅.
一些假设:图书馆将处理数百万本书; 我不认为图书规则太复杂,平均每条规则最多3个简单的字段限制; 系统需要处理的学生数量在100K范围内,因此负载相当重.我的问题是:如果加载了一百万本图书规则,Drools会占用多少内存?所有这些百万条规则的解雇速度有多快?如果Drools是合适的,我想听听一些有经验的用户设计这样一个系统的最佳实践.谢谢.
Mic*_*uff 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
Run Code Online (Sandbox Code Playgroud)
但我实际上不会这样做!
这就是我改变问题的方法:不向用户显示书籍是一种糟糕的体验.用户可能想要仔细阅读书籍以查看下次要获得的书籍.出示书籍,但不允许结帐限制书籍.这样,每个用户一次只能有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
Run Code Online (Sandbox Code Playgroud)
我在使用activation-group来确保只触发一个规则,以及确保按照我希望的顺序触发它们的突出性.
最后,保持缓存规则.Drools允许 - 并建议您 - 只将规则加载到知识库中一次,然后从中创建会话.知识库昂贵,会话便宜.
我与Drools的(或一般规则引擎)的经验是,它是一个不错的选择,如果用户的可视性规则是重要的,或者快速变化的规则,而不使其编码的项目是非常重要的,或者如果一套规则非常大,因此难以管理,思考和分析代码(所以你会让商界人士要求技术人员去阅读代码并告诉他们在情况X中会发生什么).
话虽这么说,规则引擎可能是一个瓶颈.它们不会运行任何接近代码性能的东西,因此您需要在架构上预先管理它.在这个特定的情况下,肯定有一个数据库,你可以添加到性能问题,数据库将返回一个查询比你在代码中分析整个集合快得多.
我绝对不会通过制作一百万个规则对象来实现它,而是我会制作一个可以分配多本书的书籍类型,并针对书籍类型运行规则,然后只显示允许类型的书籍.这样,您可以加载类型,通过规则引擎传递它们,然后将允许的类型推送到数据库端的查询,该查询将提取允许类型的书籍列表.
类型得到位由事实复杂,这将有可能在实践中一本书可能是两种类型(允许的,如果你正在服用一定疗程,或在一般的,如果你是该部门的一部分),但是这种方法仍然应该持有.
| 归档时间: |
|
| 查看次数: |
8427 次 |
| 最近记录: |