扩展

eKuiper 允许用户自定义扩展,以支持更多功能。 用户可以通过原生 golang 插件系统编写扩展插件,或者通过eKuiper portable 插件系统编写扩展插件,后者支持更多语言。此外,用户也可以通过配置的方式扩展 SQL 中的函数,用于调用外部已有的 REST 或 RPC 服务。

上述 3 种扩展方法都有其自身适合的场景。 一般来说,原生插件的性能最好,但最为复杂,兼容性最低。 Portable 插件在性能和复杂性之间有更好的平衡。 外部扩展不需要编码,但资源消耗最大,只支持函数扩展。本文将介绍每种扩展方法的特点,并讨论具体使用场景。

原生插件扩展

原生插件扩展利用原生 golang 插件系统在运行时动态加载自定义扩展。 eKuiper 最初支持原生插件。 但是由于 golang 插件系统本身的原因,有许多限制,例如:

  • 仅支持 Linux、FreeBSD 和 MacOS 操作系统,不支持 Alpine linux 。
  • 插件只初始化一次,不能关闭,即插件安装后无法卸载和管理。
  • 对构建和部署的要求非常苛刻,给社区带来了很多问题。 例如,插件必须使用与 eKuiper 程序完全相同的 go 版本、依赖版本等构建。 也就是说,在升级 eKuiper 主程序时,总是需要重新构建插件。

安装后,原生插件像原生代码一样运行,可以与主程序共享或传输内存中的数据,从而保证最佳性能。

因此,原生插件扩展适用于以下情况:用户只在支持的操作系统和环境中运行,在更新期间有能力或基础设施重建插件,不需要在运行时卸载插件,只使用 golang 语言系统。

Portable插件扩展

Portable插件扩展是利用 eKuiper 自身基于 IPC 通信实现的插件系统。 它有可能支持所有编程语言,目前支持 gopython。 与原生插件相比,它是可移植的,因为插件将在单独的进程中运行,并且没有那些苛刻的构建/部署要求。

portable 插件扩展旨在提供与原生插件相同的功能,但支持更简单的构建和部署。 如果开发者使用 go,甚至可以通过非常小的修改来重用插件代码,可以只构建和部署独立的插件。

因此,portable 插件扩展是对原生插件的补充。 它适用于使用多种编程语言进行编码的情况,构建一次即可在所有版本运行。

外部函数扩展

外部函数扩展通过提供一种配置的方式,使得 eKuiper 可以使用 SQL 以函数的方式直接调用外部服务,包括各种 rpc 服务、 http 服务等。该方式将可大大提高 eKuiper 扩展的易用性。外部函数将作为插件系统的补充,仅在性能要求较高的情况下才建议使用插件。

以 getFeature 函数为例,假设有 AI 服务基于 grpc 提供 getFeature 服务。则可在 eKuiper 配置之后,使用 SELECT getFeature(self) from demo 的方式,无需定制插件,即可调用该 AI 服务。

详细配置方法,请参考外部函数

当用户已经导出服务并且不想编写代码时,这种方法很有用, 它可以轻松实现 SQL 函数的批量扩展。

对比

让我们对这 3 种方法进行一些比较。 在下表中,动态重载 表示插件是否可以在运行时更新或删除。 更新时重建 表示更新主程序时是否需要重建插件。 如果是,版本更新将变得复杂。 独立进程 意味着插件是否独立于主程序运行。 如果是,插件崩溃不会影响主程序。 通信 表示主程序和插件之间如何进行通信。内存通信是最有效的方法,要求主程序和插件在同一个进程中运行。 IPC (进程间通信)需要在同一台机器上运行,具有中等的性能和依赖性。 Web 通信是指通过 TCP 等 Web 协议进行通信,可以在不同的机器上运行。

扩展 扩展类型 需要编码? 语言 操作系统 动态重载 更新时重建? 独立进程? 通信
原生 源,目标,函数 Go Linux, FreeBSD, MacOs 内存通信
Portable 源,目标,函数 Go, Python ,将来更多 任意 IPC
外部 函数 JSON, protobuf 任意 Web