SPL 报表开发:热切换和微服务化
背景
报表作为业务决策的重要依据却有着不稳定的特点,随时需要根据新的需求进行调整和优化。这种频繁的调整和更新要求报表系统具备极高的灵活性和响应速度。换句话说,报表应用能够在不停止服务的情况下,实时反映出最新的变化,也就是热切换。
理论上,实现报表的热切换并不复杂。大部分报表工具开发的模板通常是解释执行的,天然支持热切换。但报表开发不仅仅涉及报表模板的设计,还涉及报表的数据准备。如果仅仅使用 SQL 那还没什么问题,但由于报表业务的复杂性,数据从原始形式到报表可用往往需要非常复杂的加工过程,这就需要大量借助存储过程或 Java 程序来实现数据准备。而这两种方式都需要编译后才能运行,无法做到热切换,尤其是 Java。由于现代应用大多采用 Java 开发,报表通常也嵌入到应用内使用,既然报表是系统的一部分,业务逻辑又这么复杂,数据准备的任务自然落到 Java 身上,热切换也就难以实现了。
这种割裂导致了一个荒诞现象:报表模板可以实时更新,但数据准备层却需要 "熄火检修"。报表业务的“双高”(高复杂性和高实时性)俨然已经成为一对主要矛盾。
SPL 方案
esProc SPL 作为开源计算引擎具备脚本解释执行和易集成的特点,可以很好解决报表热切换的难题。
热切换的 SPL 脚本
可以用 SPL 替代存储过程和 Java 实现报表数据准备的原因之一是:其具备强大计算能力的同时代码解释执行。
如前所述,涉及存储过程和 Java 的数据准备过程往往都比较复杂,而 SPL 拥有完善的计算能力,这些计算转为 SPL 实现会更简单,甚至还可以替代复杂 SQL。
更重要的是,SPL 代码是解释执行的,天然支持热切换。早期报表都是 Java 硬写的,后来出现了报表工具,将数据呈现进行了工具化,做出来的报表模板是解释执行的,也就可以热切换。但数据准备碰到 Java 之类的还是不行,所以也要把这个阶段工具化,用 SPL 就能达到这个效果了。
这里给一个例子感受一下。
我们要找出当年销售额占到一半的前 n 个客户(大客户)的订单情况,脚本命名为:customer.splx。
脚本中参数 p_year 是报表传递过来的年份,在脚本编写前需要设置该参数:
脚本内容:
A |
|
1 |
=db.query(“select customer,amout from orders where year(order_date)=?”,p_year) |
2 |
=A1.groups(customer;sum(amount):amount).sort(amount:-1) |
3 |
=A2.sum(amount)/2 |
4 |
=0 |
5 |
=A2.pselect((A4=A4+amount,A4>=A3)) |
6 |
=A2.(customer).to(,A5) |
7 |
=A1.select(A6.pos(A1.customer)) |
8 |
return A7 |
现在由于去年的销售额大幅增长,更改了大客户的定义,将销售额在前 40% 的客户定义为大客户,需要修改计算方式。以往需要改代码再重启生效,现在不用了,修改 A3 变为:=A2.sum(amount)*0.6
,修改脚本后报表实时生效,实现热切换。
集成进应用
与报表应用结合只热切换还不够,还要能与报表无缝结合。SPL 采用 Java 开发,且提供了标准的 JDBC 接口,可以和 Java 报表无缝集成。只要将 SPL JDBC 的 jar 包引入到报表应用即可。
然后在报表数据集中,使用访问存储过程的方式调用 SPL 脚本即可获得 SPL 的计算结果。比如:
call customer(?)
这里的 customer 就是前面编写的 customer.splx 脚本名称,问号是传递的参数。
微服务化
借助 SPL 的热切换、完善计算能力和与 Java 的无缝集成,报表开发不仅能提升开发效率,还能为微服务化架构铺平道路。通过将报表数据准备独立成微服务,能够更灵活地进行报表更新和扩展。SPL 的热切换特性,让报表服务能够实时响应业务需求的变化。同时有性能需要时可以实现横向扩展,从而提升处理能力。SPL 的独立计算能力,使得报表服务的计算不再受限于数据库,可以更加高效地支持高并发的计算任务。
英文版