9

大学の図書館システムを使用して、ユースケースを説明します。学生は図書館システムに登録し、プロフィールを提供します:性別、年齢、学部、以前に完了したコース、現在登録されているコース、すでに借りている本など。図書館システムの各本は、たとえば、学生のプロフィールに基づいていくつかの借り入れルールを定義します。 、コンピュータアルゴリズムの教科書は、現在そのクラスに登録されている学生のみが借りることができます。別の教科書は数学科の学生だけが借りることができます。学生が借りることができるコンピュータネットワークの本はせいぜい2冊だけであるという規則もあり得ます。借用規則の結果、学生が図書館システムで検索/閲覧すると、借用できる本のみが表示されます。それで、

これが私がDroolsを使用してデザインをビジョン化する方法です-各本にはLHSとして学生プロファイルにいくつかのフィールド制約があるルールがあり、本ルールのRHSは単に本IDをグローバル結果リストに追加し、次にすべての本ルールを追加しますRuleBaseにロードされます。学生が図書館システムを検索/閲覧すると、RuleBaseからステートレスセッションが作成され、学生のプロファイルが事実としてアサートされます。その後、学生が借りることができるすべての本がその本のルールを実行し、あなたはその本の完全なリストを取得します。学生はグローバル結果リストで借りることができます。

いくつかの仮定:図書館は何百万冊もの本を扱うでしょう。本のルールが複雑すぎるとは思いません。平均して、各ルールに3つの単純なフィールド制約があります。システムが処理する必要のある学生の数は100Kの範囲であるため、負荷はかなり重いです。私の質問は次のとおりです。100万冊の本のルールがロードされた場合、Droolsはどのくらいのメモリを消費しますか?これらの百万のルールすべてが実行されるのはどれくらいの速さでしょうか?Droolsが適切な場合は、経験豊富なユーザーから、そのようなシステムを設計するためのいくつかのベストプラクティスを聞きたいと思います。ありがとう。

4

5 に答える 5

11

まず、すべての本にルールを作らないでください。制限に関するルールを作成します。本よりもはるかに少ない制限が定義されています。これは、実行時間とメモリ使用量に大きな影響を与えます。

大量の本をルール エンジンで実行すると、コストがかかります。特に、すべての結果をユーザーに表示するわけではないため、1 ページあたり 10 ~ 50 のみです。頭に浮かぶアイデアの 1 つは、ルール エンジンを使用して一連のクエリ条件を作成することです。(私は実際にはこれを行いません。以下を参照してください。)

これが私が考えていることです:

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

アクティベーション グループを使用して 1 つのルールのみが実行されるようにし、salience を使用して希望する順序で実行されるようにします。

最後に、ルールをキャッシュしたままにします。Drools では、ルールを 1 回だけナレッジ ベースにロードし、そこからセッションを作成することができます (また、そのように提案されています)。ナレッジ ベースは高価ですが、セッションは安価です。

于 2010-02-17T08:23:35.610 に答える
7

Drools (または一般的なルール エンジン) に関する私の経験では、ルールに対するユーザーの可視性が重要な場合、またはコーディング プロジェクトにせずにルールを迅速に変更することが重要な場合、または一連のルールが重要である場合に適しています。非常に大きいため、コードでの管理、検討、分析が難しくなります (そのため、ビジネス担当者が技術担当者にコードを読んで、状況 X で何が起こるかを伝えるように依頼することになります)。

そうは言っても、ルール エンジンがボトルネックになる可能性があります。コードのパフォーマンスに近いものは実行されないため、事前にアーキテクチャを管理する必要があります。この特定のケースでは、確かにこの背後にデータベースがあり、コードでセット全体を分析するよりもはるかに高速にデータベースがクエリを返すというパフォーマンスの問題を追加できます。

100 万個のルール オブジェクトを作成してそれを実装することは絶対にありません。むしろ、複数の書籍を割り当てることができる書籍タイプを作成し、書籍タイプに対してルールを実行してから、許可されたタイプの書籍のみを表示します。このようにして、タイプをロードし、それらをルール エンジンに渡し、許可されたタイプの書籍のリストをプルするデータベース側のクエリに許可されたタイプをプッシュできます。

実際には本が 2 つのタイプである可能性が高いため、タイプは少し複雑になります (特定のコースを受講している場合、または一般的に学科の一部である場合は許容されます) が、アプローチは依然として保持されます。 .

于 2010-02-16T17:57:47.513 に答える
1

私の質問は次のとおりです。100 万のブック ルールをロードした場合、Drools はどのくらいのメモリを消費しますか? これらの数百万のルールすべてが実行されるまでの時間はどれくらいでしょうか?

あなたのコンピュータはどれくらい速く、どれくらいのメモリを持っていますか? ある意味では、概念実証を構築し、それに適切な量の (ランダムに生成された) テスト データを入力することによってのみ確認できます。私の経験では、Drools は予想よりも高速であり、何が原因で速度が低下するかを予測するには、その内部にあるものについて十分な知識を持っている必要があります。

100 万のルールではなく、100 万のルール セッション ファクト(つまり、Book オブジェクト)について話していることに注意してください。起動に時間がかからないルールはほんの一握りです。Drools は新しいファクトごとにアジェンダに適用するルールを決定する必要があるため、潜在的に遅い部分は何百万ものオブジェクトを挿入することです。

何百万もの事実がある特定の設定について、私たちの誰も答えを持っていないのは残念です.

実装に関しては、学生がチェックアウトしたい書籍ごとに Book オブジェクトを挿入し、許可されていない書籍を撤回し、残りの (許可された) Book オブジェクトを取得するためのクエリと、理由のリストを取得します。または、ルールで設定できる追加boolean allowedの およびプロパティを持つ RequestedBook オブジェクトを使用します。String reasonDisallowed

于 2010-08-26T11:17:16.787 に答える
1

大規模なデータセット (この質問は ... Drools が大規模なデータセットのケースに適しているかどうかに関するものです) を見ているときはいつでも、既成概念にとらわれずに考えてください (以下)。「何百万ものオブジェクト」または同様の log-N タイプの問題について話しているときはいつでも、問題のツールが必ずしも問題であるとは思いません。はい、Drools (または JBoss Rules) を使用できますが、特定のコンテキストでのみ意味があります...

何かの log-N がある場合 (入力に対して大規模なデータセットを相互参照する場合)、データベースに基づくブルーム フィルターなどのより斬新なアプローチを使用することをお勧めします。これらは Java オブジェクトとして実装でき、Drools がファクト ルックアップのために参照できます (カスタム コーディングがあります)。

ブルーム フィルターは、基本的な insert()/contains() 関数のみを備えた小さなメモリ構造であるため、欠点があります...約 1% の誤検知率です。したがって、これは一次キャッシュとして機能します。Drools の質問が一般的に答えとして「いいえ」になるように構成する場合、Bloom Filter を使用したファクト テーブル構成のルックアップは非常に高速で、メモリ フットプリントが小さい (私の実装ではレコードあたり約 1.1 バイト) ため、1 MB の RAM が必要です。この場合。次に、「含む」ケース (誤検知の可能性があります) では、データベースに基づくファクト テーブルを使用して明確にします。繰り返しになりますが、ルックアップが 80% の確率で false である場合、ブルーム フィルターはメモリと時間の大幅な節約になります。そうしないと、純粋な (何でも - Drools ファクト、データベースなど) 1M レコードのルックアップは、毎回非常に高価になります (メモリと速度)。

于 2012-12-10T17:49:58.873 に答える
-1

ルールの数を学生の数の関数にする必要があることを心配しています-これは本当に厄介なことになる可能性があります(それが最大の問題のように聞こえます)。

于 2010-02-16T22:12:25.600 に答える