1. 引言

什么是规则引擎

一个业务规则包含一组条件和在此条件下执行的操作,它们表示业务规则应用程序的一段业务逻辑。业务规则通常应该由业务分析人员和策略管理者开发和修改,但有些复杂的业务规则也可以由技术人员使用面向对象的技术语言或脚本来定制。业务规则的理论基础是:设置一个或多个条件,当满足这些条件时会触发一个或多个操作。

规则引擎(rule engine)是指将复杂的业务逻辑抽象成规则,然后使用特定的算法(比如Rete)对规则进行求值等操作。简单点说,规则引擎就是实现复杂业务逻辑的框架。

为什么要用规则引擎

在维护和更新项目的业务逻辑代码时,大家深有体会:

  • 因编码风格的问题,不同人有不同的代码实现,而造成代码理解的困难;
  • 每一次业务逻辑的更改会导致项目的重编译;
  • 为了能实时响应更改,而不得不做服务重启的无缝衔接

从上面的需求出发,规则引擎应满足如下特点:

  • 脚本化,允许用类Python的脚本语言或DSL来描述规则;
  • 动态化,实时动态地加载规则脚本,规则的修改能实时地反馈于服务系统;
  • 快速的执行速度。

2. 实现

已有的开源方案

Drools应该是Java界名头最响、功能最丰富、社区最活跃的开源规则引擎了,目前的版本号为6.5.0.Final。淘宝也开源了自己的一套规则引擎QLExpress,但是似乎在2011年后项目没有再维护了。相较于QLExpress,Drools设计一套类DSL的脚本语言,用起来非常爽。但是在我看来,对于特定场景(比如用户画像),Drools显得过于重量级了,而QLExpress设计的API过于Java化了。

Scala方案

为了做到脚本化与动态化,Scala化的规则引擎将会把规则作为Scala Script独立出来,采用动态编译来加载。第三方Scala库hammurabiscalascriptengine完美地契合了需求。其中,hammurabi是规则引擎的具体实现,scalascriptengine用于对scala文件做动态编译。虽然hammurabi没有wiki,但是DZone上有一篇介绍使用的文章。scalascriptengine的版本号"com.googlecode.scalascriptengine" % "scalascriptengine_2.11" % "1.3.10"

ScalaScriptEngine的API为java.io.File;为了与Spark做集成,我们不得不做接口封装——从HDFS路径得到local File对象。基本思路便是把HDFS目录拷贝到本地的目标路径,然后基于本地路径new File对象:

import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.{FileSystem, Path}
import java.io.File implicit def path2File(hdfsPath: String): File = {
val fs = FileSystem.get(new Configuration)
val dstDir = System.getProperty("java.io.tmpdir") + "/scala-tmp"
val dstPath = new Path(dstDir)
fs.deleteOnExit(dstPath)
fs.copyToLocalFile(new Path(hdfsPath), dstPath)
new File(dstDir)
}

由HDFS路径(作为Scala Script的package根目录)导入规则脚本生成规则集合对象:

import com.googlecode.scalascriptengine.ScalaScriptEngine

def loadRules[T](sourceDir: String, className: String): T = {
val sse = ScalaScriptEngine.onChangeRefresh(sourceDir)
// delete all compiled classes (i.e. from previous runs)
sse.deleteAllClassesInOutputDirectory()
sse.refresh
sse.newInstance[T](className)
}

为了使得规则集合具有类型,而特地定义了RulesTrait:

// RulesTrait.scala
package rule.util import hammurabi.Rule trait RulesTrait {
val rules: Set[Rule]
} // User.scala
case class User(uid: String, apps: Array[String]) {
val tags = mutable.Set.empty[String] override def toString: String = "uid: %s, apps: %s, tags: %s".format(uid, apps.mkString, tags)
}

Scala Script所描述的业务规则集合(用于给用户打标签)如下:

import hammurabi.Rule
import _root_.rule.util.{RulesTrait, User}
import hammurabi.Rule._ class TagRules extends RulesTrait { override val rules: Set[Rule] = Set(
rule("add 母婴 Tag") let {
val u = any(kindOf[User])
when {
u.apps.mkString.matches(".*(孕|宝宝|育儿).*")
} then {
u.tags += "母婴"
}
},
rule("add 大学生 Tag") let {
val u = any(kindOf[User])
when {
u.apps.mkString.matches(".*(四级|六级|大学).*")
} then {
u.tags += "大学生"
}
}
)
} object TagRules {
}

在Spark程序中集成规则引擎:

import rule.util.{RulesTrait, User}

val rulesObj = loadRules[RulesTrait](params.scriptPath, "TagRules")
val ruleEngine = RuleEngine(rulesObj.rules)
val engineBC = sc.broadcast(ruleEngine) val log: RDD[User]
val tagRdd = log.mapPartitions { iter =>
val seq = iter.toSeq
val workingMemory = WorkingMemory(seq)
engineBC.value execOn workingMemory
seq.filter(_.tags.nonEmpty).toIterator
}

3. 参考资料

[1] 李国乐, Java规则引擎与其API(JSR-94).

[2] Ricardo Olivieri, 使用 Drools 规则引擎实现业务逻辑.

Scala化规则引擎的更多相关文章

  1. Flink/CEP/规则引擎/风控

    基于 Apache Flink 和规则引擎的实时风控解决方案 ​ 对一个互联网产品来说,典型的风控场景包括:注册风控.登陆风控.交易风控.活动风控等,而风控的最佳效果是防患于未然,所以事前事中和事后三 ...

  2. Asp.net 面向接口可扩展框架之业务规则引擎扩展组件

    随着面向接口可扩展框架的继续开发,有些功能开发出现了"瓶颈",有太多的东西要写死才好做.但写死的代码扩展性是非常的不好,迷茫中寻找出入... 进而想到我以前开发的好几个项目,都已有 ...

  3. 小明历险记:规则引擎drools教程一

    小明是一家互联网公司的软件工程师,他们公司为了吸引新用户经常会搞活动,小明常常为了做活动加班加点很烦躁,这不今天呀又来了一个活动需求,我们大家一起帮他看看. 小明的烦恼 活动规则是根据用户购买订单的金 ...

  4. 使用CKRule规则引擎处理多变业务

    1, 多变业务 开发系统时,有没有试过下面的情况,如果你试过,那可以考虑一下使用规则引擎了. 序号 问题 举例 1 业务规则来自于一个或多个表格 商店的会员积分表,停车场的计费标准,快递费的计算表,客 ...

  5. 【java规则引擎】之规则引擎解释

    转载:http://www.open-open.com/lib/view/open1417528754230.html 现实生活中,规则无处不在.法律.法规和各种制度均是:对于企业级应用来说,在IT技 ...

  6. Java规则引擎drools:drt动态生成规则并附上具体项目逻辑

    一 整合 由于本人的码云太多太乱了,于是决定一个一个的整合到一个springboot项目里面. 附上自己的项目地址https://github.com/247292980/spring-boot 以整 ...

  7. .NET RulesEngine(规则引擎)

    一次偶然的机会,让我拿出RulesEngine去完成一个业务,对于业务来说主要是完成一个可伸缩性(不确定的类型,以及不确定的条件,条件的变动可能是持续增加修改的)的业务判断.比如说完成一个成就系统,管 ...

  8. 规则引擎深度对比,LiteFlow vs Drools!

    前言 Drools是一款老牌的java规则引擎框架,早在十几年前,我刚工作的时候,曾在一家第三方支付企业工作.在核心的支付路由层面我记得就是用Drools来做的. 难能可贵的是,Drools这个项目在 ...

  9. Atitit.工作流 与 规则引擎

    Atitit.工作流 与 规则引擎 1.1. 应用来说,通常分为三部分:界面.业务逻辑和存储1 1.2. 自定义操作系列1 1.3. 自定义按钮系列2 1.1. 应用来说,通常分为三部分:界面.业务逻 ...

随机推荐

  1. Java基础Collection集合

    1.Collection是所有集合的父类,在JDK1.5之后又加入了Iterable超级类(可以不用了解) 2.学习集合从Collection开始,所有集合都继承了他的方法 集合结构如图:

  2. Linux中进行单文件内容的复制

    文件内容复制的常规方法: 开辟一段空间,不断读取文件的内容并写入另一文件当中,这种方法好在安全,一般在类型允许的最大范围内是安全的,缺点就是复制内容的时间长 一次性复制文件的内容,这种方法必须首先获取 ...

  3. C语言动态走迷宫

    曾经用C语言做过的动态走迷宫程序,先分享代码如下: 代码如下: //头文件 #include<stdio.h> #include<windows.h>//Sleep(500)函 ...

  4. 在.NET Core之前,实现.Net跨平台之Mono+CentOS+Jexus初体验

    准备工作 本篇文章采用Mono+CentOS+Jexus的方式实现部署.Net的Web应用程序(实战,上线项目). 不懂Mono的请移步张善友大神的:国内 Mono 相关文章汇总 不懂Jexus为何物 ...

  5. Spring cache简单使用guava cache

    Spring cache简单使用 前言 spring有一套和各种缓存的集成方式.类似于sl4j,你可以选择log框架实现,也一样可以实现缓存实现,比如ehcache,guava cache. [TOC ...

  6. Consul-template的简单应用:配置中心,服务发现与健康监测

    简介 Consul-template是Consul的一个方扩展工具,通过监听Consul中的数据可以动态修改一些配置文件,大家比较热衷于应用在Nginx,HAProxy上动态配置健康状态下的客户端反向 ...

  7. GJM : C#设计模式汇总整理——导航 【原创】

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...

  8. ABP理论之CSRF

    返回总目录 本篇目录 介绍 ASP.NET MVC ASP.NET WEB API ASP.NET Core[以后补上] 客户端类库 内部原理 介绍 CSRF[Cross-Site Request F ...

  9. 集成基于CAS协议的单点登陆

    相信大家对单点登陆(SSO,Single Sign On)这个名词并不感到陌生吧?简单地说,单点登陆允许多个应用使用同一个登陆服务.一旦一个用户登陆了一个支持单点登陆的应用,那么在进入其它使用同一单点 ...

  10. 在C#代码中应用Log4Net系列教程(附源代码)

    Log4Net应该可以说是DotNet中最流行的开源日志组件了.以前需要苦逼写的日志类,在Log4Net中简单地配置一下就搞定了.没用过Log4Net,真心不知道原来日志组件也可以做得这么灵活,当然这 ...