【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(逻辑模型和API设计)(一)

简介: 【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(逻辑模型和API设计)

规则引擎是什么

规则引擎是一种基于规则的软件系统,它可以自动化地执行规则,从而实现业务流程控制、风险管理、决策支持等功能。规则引擎通常由三个主要组件组成:规则信息库、逻辑推理引擎和执行引擎。



规则信息库

规则信息库是规则引擎的数据核心,它包含了所有的规则。

规则可以是 业务规则决策规则计算规则 等等。规则信息库通常采用类似于数据库的结构来存储规则,每个规则都有一个唯一的标识符、一个条件部分和一个结果部分。

  • 条件部分描述了规则的前提条件
  • 结果部分描述了规则的执行结果

逻辑推理引擎

逻辑推理引擎是规则引擎的计算核心,它负责根据规则信息库中的规则和输入数据来推导出结果。

逻辑推理引擎通常采用基于规则的推理机制,即根据规则的前提条件和输入数据来匹配规则,并执行规则的结果部分。

推理引擎还可以支持多种推理算法,如前向推理、后向推理、混合推理等。

程序执行引擎

程序执行引擎是规则引擎的执行核心,它负责将推理引擎计算出的结果应用到实际业务中。

程序执行引擎通常采用类似于工作流引擎的方式来执行规则,即按照规则的执行顺序来依次执行规则组件。程序执行引擎还可以支持多种执行方式,如同步执行、异步执行、批量执行、延时执行或者定时执行等。

程序执行引擎的优点在于它可以将 业务规则计算逻辑 从应用程序中分离出来,从而实现 业务逻辑可配置可扩展可重用 。程序执行引擎还可以提高业务流程的自动化程度,减少人工干预,提高业务处理效率和准确性。

总之,规则引擎是一种强大的软件工具,它可以帮助企业实现业务流程控制、风险管理、决策支持等功能,提高业务处理效率和准确性

规则引擎的使用场景

当然可以,请问您需要的规则引擎是用于什么样的场景和目的呢?例如,是用于业务流程控制、风险管理、决策支持等方面。同时,您需要考虑的因素还包括规则的复杂度、数据量、性能要求等等。


规则引擎的核心逻辑模型的介绍

以下是规则引擎的核心逻辑模型的大概架构图,如下所示:


接下来我们,针对于Rule规则模型以及RuleEngine运作引擎模型的大概行为以及服务能力进行相关的介绍和说明。

Rule规则模型

Rule规则模型属于规则引擎中最基础的数据信息模型,同样也是整个规则引擎执行逻辑的“物质基础”,它为程序执行引擎和逻辑推理引擎提供了根本方向。它主要由三部分组成:


Action- 触发行为

Action(触发行为)主要表示为执行某种行为或者操作的模式,大家可以理解为执行处理的一个操作。例如:当我们发觉我们饿了,我们就应该去吃饭,而这里的“吃饭”代表着就是Action行为操作。至于吃什么,就如同我们的参数一样,传递苹果我们就吃苹果;传递香蕉,我们就吃香蕉。

代码案例

下面我们代码去实现一个Action触发的接口模型,其中Action触发行为的视实现,只有通过

java

复制代码

@FunctionalInterface
public interface Action {
    void execute(Facts facts) throws Exception;
}

从以上代码可以看出,该代码段主要代表了值的执行行为和内容。其中,它的参数类型为Facts。Facts是用户可以自定义的事实,它表示实际的参数,也可以称为事实参数(Fact Parameters)。关于Facts的具体内容,我们将在后面的参数部分进行介绍,目前暂时不进行过多赘述。

大家只要知道Action接口主要用于定义我们的执行行为就可以了,当规则的条件评估为 "true "时执行操作。

Condition-条件判断

Condition的条件接口,主要用于控制和判断是否要执行上面所定义的Action接口所要执行的行为动作,通过evaluate方法的返回值,从而判断是否需要进行执行Action接口的实际功能。下面则是我们定义的Condtion条件判断接口的执行逻辑代码。

java

复制代码

@FunctionalInterface
public interface Condition {
    /**
     * Evaluate the condition according to the known facts.
     * @param facts known when evaluating the rule.
     * @return true if the rule should be triggered, false otherwise
     */
    boolean evaluate(Facts facts);
    /**
     * A NoOp {@link Condition} that always returns false.
     */
    Condition FALSE = facts -> false;
    /**
     * A NoOp {@link Condition} that always returns true.
     */
    Condition TRUE = facts -> true;
}

其中这两个字段,主要用于Lamda表达式作为一个变量处理。因为属于Lamda表达式,所以不会立刻加载,属于懒惰操作加载处理。

java

复制代码

/**
     * A NoOp {@link Condition} that always returns false.
     */
    Condition FALSE = facts -> false;
    /**
     * A NoOp {@link Condition} that always returns true.
     */
    Condition TRUE = facts -> true;

从对于Condition接口的定义的evaluate(Facts facts);方法,可以看出来,它的参数也是Facts。因此可以的得出结论,Condition也是根据实际情况的参数进行判断是否符合满足条件进行执行对应的Condition条件。

Parameter-实际参数

首先Parameter的实际参数模型,主要属于一个抽象、泛化的类型数据模型,最简单也最方便的数据模型就是Map数据模型。但是由于Map的性能以及一些定制化功能的开发量过多,所以我们再次没有选择Map,而是选择了自定义K-V结构化的数据模型。



Fact的参数模型

当涉及到Fact数据模型子元素时,它通常采用键-值(K-V)结构。这种结构由两部分组成:键(Key)和对应的值(Value)。键用于标识和索引数据,而值则包含了与该键相关联的具体信息。

Fact数据模型子元素的关键特点是它们的多样性和可扩展性。通过使用K-V结构,我们可以根据实际需求存储和表达各种类型的数据。例如,对于一个商品,可以使用键值对来表示商品的名称、价格、描述等信息。

另一个重要的特征是Fact的可组合性。多个Fact数据模型子元素可以组合成一个更复杂的数据集合。这种组合性使得我们能够处理和管理大量的数据,并在需要时对其进行灵活的访问和操作。

总结一下,Fact数据模型子元素是基于K-V结构的,用于存储和表示各种类型数据的元素。它们具有多样性、可扩展性和可组合性的特点,使我们能够有效地处理和管理复杂的数据集合。

代码案例

java

复制代码

public class Fact<T> {
  private final String name;
  private final T value;
  /**
   * Create a new fact.
   * @param name of the fact
   * @param value of the fact
   */
  public Fact(String name, T value) {
    Objects.requireNonNull(name, "name must not be null");
    Objects.requireNonNull(value, "value must not be null");
    this.name = name;
    this.value = value;
  }
  /**
   * Get the fact name.
   * @return fact name
   */
  public String getName() {
    return name;
  }
  /**
   * Get the fact value.
   * @return fact value
   */
  public T getValue() {
    return value;
  }
  @Override
  public String toString() {
    return "Fact{" +
        "name='" + name + '\'' +
        ", value=" + value +
        '}';
  }
  /*
   * The Facts API represents a namespace for facts where each fact has a unique name.
   * Hence, equals/hashcode are deliberately calculated only on the fact name.
   */
  
  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Fact<?> fact = (Fact<?>) o;
    return name.equals(fact.name);
  }
  @Override
  public int hashCode() {
    return Objects.hash(name);
  }
}
Facts的参数模型

在这种情况下,参数主要由Fact数据模型子元素(K-V结构)和K-V结构体集合组成。实际过程中可能会有多个K-V对应的数据需要传输,因此需要使用另一个容器来组装参数数据集合模型,即Facts。Facts表示多个Fact,即多个K-V结构的数据集合。

java

复制代码

public class Facts implements Iterable<Fact<?>> {
    private final Set<Fact<?>> facts = new HashSet<>();
    /**
     * Add a fact, replacing any fact with the same name.
     *
     * @param name of the fact to add, must not be null
     * @param value of the fact to add, must not be null
     */
    public <T> void put(String name, T value) {
        Objects.requireNonNull(name, "fact name must not be null");
        Objects.requireNonNull(value, "fact value must not be null");
        Fact<?> retrievedFact = getFact(name);
        if (retrievedFact != null) {
            remove(retrievedFact);
        }
        add(new Fact<>(name, value));
    }
    
    /**
     * Add a fact, replacing any fact with the same name.
     * 
     * @param fact to add, must not be null
     */
    public <T> void add(Fact<T> fact) {
        Objects.requireNonNull(fact, "fact must not be null");
        Fact<?> retrievedFact = getFact(fact.getName());
        if (retrievedFact != null) {
            remove(retrievedFact);
        }
        facts.add(fact);
    }
    /**
     * Remove a fact by name.
     *
     * @param factName name of the fact to remove, must not be null
     */
    public void remove(String factName) {
        Objects.requireNonNull(factName, "fact name must not be null");
        Fact<?> fact = getFact(factName);
        if (fact != null) {
            remove(fact);
        }
    }
    /**
     * Remove a fact.
     *
     * @param fact to remove, must not be null
     */
    public <T> void remove(Fact<T> fact) {
        Objects.requireNonNull(fact, "fact must not be null");
        facts.remove(fact);
    }
    /**
     * Get the value of a fact by its name. This is a convenience method provided
     * as a short version of {@code getFact(factName).getValue()}.
     *
     * @param factName name of the fact, must not be null
     * @param <T> type of the fact's value
     * @return the value of the fact having the given name, or null if there is
     * no fact with the given name
     */
    @SuppressWarnings("unchecked")
    public <T> T get(String factName) {
        Objects.requireNonNull(factName, "fact name must not be null");
        Fact<?> fact = getFact(factName);
        if (fact != null) {
            return (T) fact.getValue();
        }
        return null;
    }
    
    /**
     * Get a fact by name.
     *
     * @param factName name of the fact, must not be null
     * @return the fact having the given name, or null if there is no fact with the given name
     */
    public Fact<?> getFact(String factName) {
        Objects.requireNonNull(factName, "fact name must not be null");
        return facts.stream()
                .filter(fact -> fact.getName().equals(factName))
                .findFirst()
                .orElse(null);
    }
    /**
     * Return a copy of the facts as a map. It is not intended to manipulate
     * facts outside of the rules engine (aka other than manipulating them through rules).
     *
     * @return a copy of the current facts as a {@link HashMap}
     */
    public Map<String, Object> asMap() {
        Map<String, Object> map = new HashMap<>();
        for (Fact<?> fact : facts) {
            map.put(fact.getName(), fact.getValue());
        }
        return map;
    }
    /**
     * Return an iterator on the set of facts. It is not intended to remove
     * facts using this iterator outside of the rules engine (aka other than doing it through rules)
     * 
     * @return an iterator on the set of facts
     */
    @Override
    public Iterator<Fact<?>> iterator() {
        return facts.iterator();
    }
    /**
     * Clear facts.
     */
    public void clear() {
        facts.clear();
    }
    @Override
    public String toString() {
        Iterator<Fact<?>> iterator = facts.iterator();
        StringBuilder stringBuilder = new StringBuilder("[");
        while (iterator.hasNext()) {
            stringBuilder.append(iterator.next().toString());
            if (iterator.hasNext()) {
                stringBuilder.append(",");
            }
        }
        stringBuilder.append("]");
        return stringBuilder.toString();
    }
}

当看到Facts的源码时,可以发现它与线程池的Executors组件相似。事实上,Facts可以被看作是一个类似工厂方法的组件,它帮助我们维护内部的Fact集合,并提供了对这些Fact数据集合进行增加、删除、更新和查询(CRUD操作)的能力。不仅如此,Facts还能提供其他辅助方法来处理这些内部数据集合。通过使用Facts数据模型,我们能够更加高效地管理和操作数据集合。


【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(逻辑模型和API设计)(二)https://developer.aliyun.com/article/1471069

相关文章
|
18天前
|
Java API
掌握Java 8 Stream API的艺术:详解流式编程(三)
掌握Java 8 Stream API的艺术:详解流式编程
14 2
|
5天前
|
JSON 自然语言处理 Dart
私有化部署 Llama3 大模型, 支持 API 访问
通过 ollama 本地运行 Llama3 大模型其实对我们开发来说很有意义,你可以私有化放服务上了。 然后通过 api 访问,来处理我们的业务,比如翻译多语言、总结文章、提取关键字等等。 你也可以安装 enchanted 客户端去直接访问这个服务 api 使用。
123 0
私有化部署 Llama3 大模型, 支持 API 访问
|
5天前
|
存储 SQL Java
Java8 Stream API 详解:流式编程进行数据处理
Java8 Stream API 详解:流式编程进行数据处理
|
7天前
|
人工智能 API 开发者
【AI大模型应用开发】0.2 智谱AI API接入详细步骤和简单应用
【AI大模型应用开发】0.2 智谱AI API接入详细步骤和简单应用
41 0
|
7天前
|
人工智能 API Python
【AI大模型应用开发】1.1 Prompt Engineering(提示词工程)- 用OpenAI API实战,优化方法论总结
【AI大模型应用开发】1.1 Prompt Engineering(提示词工程)- 用OpenAI API实战,优化方法论总结
11 0
|
14天前
|
前端开发 BI API
API函数式组件封装逻辑
API函数式组件封装逻辑
13 0
|
18天前
|
存储 Java BI
掌握Java 8 Stream API的艺术:详解流式编程(二)
掌握Java 8 Stream API的艺术:详解流式编程
26 1
|
18天前
|
存储 Java 关系型数据库
掌握Java 8 Stream API的艺术:详解流式编程(一)
掌握Java 8 Stream API的艺术:详解流式编程
49 1
|
1天前
|
存储 缓存 运维
DataWorks操作报错合集之DataWorks根据api,调用查询文件列表接口报错如何解决
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
9 1
|
2天前
|
SQL 数据管理 API
数据管理DMS产品使用合集之阿里云DMS提供API接口来进行数据导出功能吗
阿里云数据管理DMS提供了全面的数据管理、数据库运维、数据安全、数据迁移与同步等功能,助力企业高效、安全地进行数据库管理和运维工作。以下是DMS产品使用合集的详细介绍。