Skip to content
广告❤️成为赞助商

流程模型缓存

模型缓存处理核心功能:建立 jsonjava 流程对象模型 ProcessModel 的映射关系,减少对 json 模型解析的性能损耗。

模型解析接口

模型解析接口 ProcessModelCache 主要实现分为 部署流程模型 实时流程模型 两种类型。

  • 流程定义实体类 FlwProcess 部署流程模型,主要存储建模的模板模型 该模型可以随时调整。

  • 扩展流程实例实体类 FlwExtInstance 实时流程模型,存储 正在执行实例的模型 支持动态调整 增减 节点。

java
public interface ProcessModelCache {

    /**
     * 流程模型缓存KEY
     */
    String modelCacheKey();

    /**
     * 流程模型内容
     */
    String getModelContent();

    /**
     * JSON BPM 模型
     */
    default ProcessModel model() {
        String modelContent = this.getModelContent();
        Assert.isEmpty(modelContent, "The process modelContent is Empty.");
        
        // 流程引擎上下文调用模型解析器解析,该方法会自动调用缓存实现
        return FlowLongContext.parseProcessModel(modelContent, this.modelCacheKey(), false);
    }
}
  • 修改数据库模型,即时生效需要调用缓存失效逻辑。
java
// 使缓存失效
FlowLongContext.invalidateProcessModel(flwExtInstance.modelCacheKey());

流程缓存接口

该接口为 flowlong 的全局缓存,默认 FlowSimpleCache 实现类为 ConcurrentHashMap 本地实现, 目前缓存配合 流程模型解析器 注入 FlowLongContext 流程引擎上下文。

java
public interface FlowCache {

    /**
     * 根据关键字缓存对象
     *
     * @param key      缓存关键字
     * @param value    缓存对象
     * @param duration 有效时长(单位秒)小于等于 0 不处理
     */
    void put(String key, Object value, long duration);

    /**
     * 从缓存中获取对象
     *
     * @param key 缓存关键字
     * @return 缓存对象
     */
    <T> T get(String key);

    /**
     * 根据关键字删除缓存对象
     *
     * @param key 缓存关键字
     */
    void remove(String key);

}

本地缓存 Caffeine 使用案例

  • 区别于默认 map 缓存该方案支持自动释放缓存对象节省内存。
java
@Component
public class FlowCaffeineCache implements FlowCache {
    private final Cache<String, Object> cache = Caffeine.newBuilder()
            .maximumSize(1000)  // 最大缓存数量
            .expireAfterWrite(Duration.ofHours(2))  // 2小时过期
            .expireAfterAccess(Duration.ofMinutes(30))  // 30分钟未访问过期
            .recordStats()  // 记录统计信息
            .build();

    @Override
    public void put(String key, Object value) {
        cache.put(key, value);
    }

    @Override
    public <T> T get(String key) {
        return (T) cache.getIfPresent(key);
    }

    @Override
    public void remove(String key) {
        cache.invalidate(key);
    }
}

序列化存储

  • 场景 redis 使用 jackson 序列化存储缓存场景,需要处理ProcessModel对象避免循环。
java
public void put(String key, Object value) {
    if (value instanceof ProcessModel) {
        // 清理父节点关系
        cache.put(key, ((ProcessModel) value).cleanParentNode());
    } else {
        cache.put(key, value);
    }
}

public <T> T get(String key) {
    T obj = (T) cache.getIfPresent(key);
    if (obj instanceof ProcessModel) {
        // 构建父节点关系
        ProcessModel processModel = (ProcessModel) obj;
        processModel.buildParentNode(processModel.getNodeConfig());
        return (T) processModel;
    }
    return obj;
}

提示!

在分布式应用场景下,建议使用分布式缓存实现接管,例如 redis 实现等。

更适合中国人的工作流引擎