这实际上可能与Drools本身无关,但可能只是拥有Java本机解决方案。我只是一个完整的Java noob并继承了一个项目,所以我试图了解最佳实践。
我们有一个基于规则的多租户系统,业务规则可以由我们的客户动态配置。我们将每个客户端的编译规则存储在ConcurrentHashMap
中,看起来像这样
ConcurrentMap<String, KieBase> rules = new ConcurrentHashMap<>();
string
是表示每个唯一客户端的UUID。然而,问题在于水平扩展计算是一个问题,因为这只是内存中的hashmap,每次更改都会重新编译。如果我们将其缩小,每个客户都需要听取新的规则更改并在每次发生时重新编译,这感觉就像是浪费,因为他们总会产生相同的结果。
我的最终目标是将这些计算出的规则存储在JVM之外,以便多个实例可以共享已编译的规则,并且这些实例中的任何一个都可以安全地,并发地重新编译特定客户端的规则,而所有其他实例可能需要客户等待的规则
所以我的想法是使用Redis作为k / v锁/存储,其中键是client_id,值将是Drools KieBase对象的序列化版本。重新计算会使用transaction(或某些类似的锁定算法)将redis存储锁定在该密钥上,以便需要KieBase的其他实例才能等到编译完成并写回数据库。
所以我有几个问题:
答案 0 :(得分:0)
一个简单的ObjectOutputStream足以序列化KieBase对象。下面用于写入文件,但是您可以通过写入ByteArrayOutputStream并以任一形式获取结果来创建String或byte []。
KieBase kieBase = kieContainer.getKieBase();
FileOutputStream fos = new FileOutputStream( OUTPATH );
ObjectOutputStream oos = new ObjectOutputStream( fos );
oos.writeObject( kieBase );
oos.close();
FileInputStream fis = new FileInputStream( OUTPATH );
ObjectInputStream ois = new ObjectInputStream( fis );
KieBase kieBase1 = (KieBase)ois.readObject();
ois.close();
对于锁定,这取决于您是否需要针对并行运行的多个应用程序(在网络中)锁定外部表示,或者是否存在将所有内容保留在HashMap中的单个(服务器)应用程序。在后一种情况下,任何Java对象都有一个监视器:
synchronized( idString ) {
idString.wait(); // or overloaded form with timeout
}
// different thread
synchronized( idString ){
idString.notify();
}
您可以参考Brian Goetz的书“Java Concurrency in Practice”。
修改强> 任何像样的DB都有写锁定机制。此外,在您的情况下,您甚至可以使用简单的文件存储和文件锁定进行管理,可在MS Windows和所有Unices上使用。