如何序列化JBoss Drools KieBase集合用于外部存储?

时间:2017-01-14 00:30:02

标签: java concurrency redis drools

这实际上可能与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的其他实例才能等到编译完成并写回数据库。

所以我有几个问题:

  1. 此KieBase对象的序列化是Drools特定的事物,还是Java中的任何对象都有一个通用的编组序列化机制(这是推荐的吗?)
  2. reddisson之类的内容会完全符合我的要求吗?如果是这样,有没有人有一个片段指向我正确的方向?我基本上需要锁定每个客户端的密钥,以便在计算一个实例时阻塞多个实例,但我最好不要锁定整个数据库,只是哈希映射中的一个条目。

1 个答案:

答案 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上使用。