Skip to end of metadata
Go to start of metadata

作者:Andris Zeila

Zabbix中国培训师——周松(译)

几乎每个Zabbix版本中都会新增预处理的支持方式,很明显,很多时候存在一些无法预估的业务场景,所以我们必须对此提出一个通用的解决方案。反之,这又涉及到一个重要的问题-嵌入式脚本语言/引擎。

首先,我们决定以下评估标准:

  • 引擎集成。引擎可以轻松集成,需要哪些库文件,这些库文件必须要在Zabbix支持的平台上可用,同时该引擎还必须支持Windows版本。
  • 资源使用情况。调用/回调性能是这里的首要任务,内存的使用和执行的速度是次要的。该脚本的常见用途是在从C程序调用时执行少量代码,并且需要支持脚本预编译和字节码缓存。
  • 安全。默认情况下,必须禁用文件/套接字访问等潜在危险功能。引擎必须支持超时机制和内存限制,以避免脚本卡主或占用所有的系统内存。

创建了很多测试用例来测量性能,并根据所描述的标准评估脚本引擎:

  • 华氏度到摄氏度的转换,测试简单的数学公式。
  • 字数。计算输入数据中指定单词的出现次数。
  • JSON解析。计算与指定标记/值匹配的对象数。
  • 解析apache状态页面并以JSON格式提取所需的指标。
  • Zabbix获取数据。从Zabbix获取指定数量的历史数据并计算总和。

评估了以下语言/引擎:

  • Lua – Lua 5.1(选择旧版本是因为它在旧的平台上可用)
  • Lua – LuaJIT
  • JavaScript – Duktape
  • JavaScript – JerryScript
  • 嵌入式Python
  • 嵌入式Perl

另外,我们还尝试了一些使用Chrome V8Spider Monkey等脚本引擎的测试不太成功对于短脚本的执行来说太重了。

结果如下:
特点:


LUA

Javascript(ECMAScript)

Python

Perl


Lua 5.1

LuaJIT

Duktape

Jerryscript

CPython 2.7

Perl 5.x

语言功能

可能需要第三方库(json),没有本机正则表达式支持(lua模式类似,但功能较弱)。

可能需要第三方库(json),没有本机正则表达式支持(lua模式类似,但功能较弱)。

没有开箱即用的文件访问支持,网络功能。

没有开箱即用的文件访问支持,网络功能。

各种模块的广泛收集。

各种模块的广泛收集。

必须为第三方或自定义模块提供附加功能。

必须为第三方或自定义模块提供附加功能。

语言功能限制

可以禁用“危险”模块和功能,但如果已知引擎内部,则可能仍然可以访问。

可以禁用“危险”模块和功能,但如果已知引擎内部,则可能仍然可以访问。

默认情况下,没有文件/网络访问可用。

默认情况下,没有文件/网络访问可用。

通过覆盖默认导入功能可以禁用模块,但是,仍然可以使用低级python howto导入这些模块。

通过覆盖默认导入功能可以禁用模块,但是,仍然可以使用低级python howto导入这些模块。

引擎集成

链接到lua和一些常见的库。

链接到lua和一些常见的库。

分发为单个C和两个头文件,包含在项目中。

必须从源代码编译jerryscript库。

链接到python和一些常见的库。

链接到perl和一些常见的库。

资源限制

可以通过限制CPU周期来限制自定义分配器和CPU使用的内存使用。

可以通过限制CPU周期来限制CPU使用率。不支持自定义内存分配器。

可以通过设置脚本超时来限制自定义分配器和CPU使用的内存使用。

JerryScript没有提供限制内存使用的方法,但它似乎有默认的512KB堆限制。尚不支持执行超时。

资源模块可以限制内存和CPU使用率。然而,基于流程ulimits,这似乎是* nix特定的。

只能应用基于OS的过程资源限制。

脚本预编译和加载

支持字节码预编译和加载。

支持字节码预编译和加载。

支持字节码预编译和加载。

支持字节码预编译和加载。

支持功能编组/解组。

不支持字节码预编译/加载。

说明




在编译脚本时使用大小不足的缓冲区时崩溃。

基于缩进的代码结构,难以在文本区域中编写更复杂的代码。需要更高级的编辑器。


性能(预编译代码):

主要关注的是预编译的字节码执行性能,但是,在预处理更改时,脚本将被重新编译,并且在错误时JavaScript引擎可能会重新初始化所以这也应该考虑在内。

从整体表现来看,Lua(特别是LuaJIT)领先。PythonPerl具有强大的字符串操作性能,但脚本编译和引擎初始化的性能最差,此外,仅支持在OS级别上CPU / memory资源限制。Duktape具有整体性能比较平均,但是脚本性能最差,尽管如此,在性能最差的情况下,它设法每秒处理400k表达式对于单个工作任务而言应该足够了。

这样就只剩下了Lua或者JavaScript。出去性能不说,JavaScript因语言流行度而获胜。Lua是一种利基语言,具有自己的语法特性。Lua模式虽然与正则表达式有些类似,但仍然不同。此外,本机JSON支持是可取的,但可以预编译和预加载第三方JSON模块,最终还是Duktape的集成更加简单。

示例

作为示例,我们将展示如何使用JavaScript预处理步骤配置华氏温度到摄氏温度的转换。在项目的预处理配置中添加新步骤并选择自定义脚本/ JavaScript

脚本的第一行显示在参数中(当前具有占位符“script”):

单击将打开一个简单的编辑器窗口:

目前,编辑器是一个使用等宽字体的简单多行编辑器。不支持制表和语法着色。

输入转换公式

return (value - 32) * 5 / 9

并按申请

对于需要多行的复杂脚本,建议在第一行注释中编写脚本描述,如:

然后脚本将在预处理步骤中执行:

虽然这个例子非常简单,但JavaScript预处理可用于复杂的场景,如分析输入数据,将文本数据转换为其他格式(JSON)等。基本上来说,当Zabbix标准预处理选项不足时,JavaScript预处理可能会是一个很好的选择。