# 扩展

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 协议进行通信,可以在不同的机器上运行。

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