Zeek Storage Framework 异步操作完全指南:Storage::Async 模块的 API 详解与源码级实战

发布时间:2026/10/8 1:27:53
Zeek Storage Framework 异步操作完全指南:Storage::Async 模块的 API 详解与源码级实战 网络安全网络IDS【免费下载链接】zeekZeek is a powerful network analysis framework that is much different from the typical IDS you may know.项目地址https://gitcode.com/gh_mirrors/ze/zeek点击查看免费下载导读本文聚焦 Zeek 的 storage framework 中异步操作模块Storage::Async。storage framework 为 Zeek 提供基于插件的短/长期数据存储能力以键值对形式在脚本层读写数据而Storage::Async是其中以when条件配合使用的异步 API 模块适用于不能阻塞 Zeek 主事件循环的场景。读完本文你将掌握open_backend/close_backend/put/get/erase五个异步函数的完整签名、参数语义、返回值结构理解异步与同步模式的分派机制并能基于仓库中的真实测试用例写出可运行的 Zeek 存储脚本。1. Storage::Async 模块概览Storage::Async定义在 scripts/base/frameworks/storage/async.zeek模块注释明确其职责为 Asynchronous operation methods for the storage frameworkstorage framework 的异步操作方法。其 API 文档即 doc/scripts/base/frameworks/storage/async.zeek.rst对应的接口摘要如下函数说明Storage::Async::open_backend基于配置对象异步打开一个新的后端连接Storage::Async::close_backend异步关闭一个已有的后端连接Storage::Async::put异步向后端插入一条新记录Storage::Async::get异步从后端取回一条记录Storage::Async::erase异步从后端删除一条记录该模块通过load ./main依赖基础模块 scripts/base/frameworks/storage/main.zeek命名空间Storage因此在使用Storage::Async之前无需手动加载main直接load base/frameworks/storage/async即可同时会获得Storage::BackendOptions、Storage::PutArgs、Storage::OperationResult等类型定义。模块的自动装载入口见 scripts/base/frameworks/storage/load.zeek。1.1 异步模式与同步模式的分工storage framework 将脚本层 API 拆分为两个平级模块Storage::Async异步与Storage::Sync同步见 scripts/base/frameworks/storage/sync.zeek。二者参数与返回值完全一致唯一区别在于异步函数必须写在when条件内调用否则会返回错误同步函数可直接调用也可以放进when但会阻塞直到后端返回数据。两者均通过各函数体内的__前缀内建函数如Storage::Async::__open_backend最终接入 src/storage/storage.bif 所声明的 C 实现因此异步 API 的底层由原生代码支撑脚本层只是分派层。2. 五个异步 API 的完整签名与语义以下签名与参数说明均严格对齐 doc/scripts/base/frameworks/storage/async.zeek.rst 及源码 scripts/base/frameworks/storage/async.zeek。2.1 open_backend异步建立后端连接function open_backend(btype: Storage::Backend, options: Storage::BackendOptions, key_type: any, val_type: any): Storage::OperationResult参数类型说明btypeStorage::Backendenum指示要打开哪种后端取值由已加载的后端插件定义内置Storage::STORAGE_BACKEND_REDIS与Storage::STORAGE_BACKEND_SQLITEoptionsStorage::BackendOptionsrecord连接配置记录后端插件可通过 redef 该记录追加自身字段key_typeany后端中键的脚本层类型用于校验传入其他方法get、erase等的键val_typeany后端中值的脚本层类型既用于校验传给put的值也用于get返回值的类型转换返回值一个Storage::OperationResult记录成功时其value字段为opaque of Storage::BackendHandle后端句柄失败时在error_str中给出错误信息。后端句柄是opaque类型与普通 Zeek 值一样可以存放在全局变量中可在zeek_init事件里打开一次、在整个 Zeek 运行期间复用。打开成功后框架会抛出Storage::backend_opened事件。2.2 close_backend异步关闭后端连接function close_backend(backend: opaque of Storage::BackendHandle) : Storage::OperationResultbackend要关闭的后端连接句柄。返回值包含操作状态与可选错误字符串的OperationResult。关闭成功后抛出Storage::backend_lost事件该事件同样会在连接意外中断时触发如 Redis 服务端掉线供脚本感知连接故障并执行重连等恢复逻辑。2.3 put异步写入键值对function put(backend: opaque of Storage::BackendHandle, args: Storage::PutArgs): Storage::OperationResultbackend后端连接句柄。argsStorage::PutArgs记录封装写入参数见下文 §3.2。返回值操作状态与可选错误字符串。2.4 get异步读取键值对function get(backend: opaque of Storage::BackendHandle, key: any) : Storage::OperationResultbackend后端连接句柄。key要查找的键。返回值成功时value字段携带所取回的值其类型与open_backend时传入的val_type一致若键不存在后端应返回Storage::KEY_NOT_FOUND。2.5 erase异步删除键值对function erase(backend: opaque of Storage::BackendHandle, key: any) : Storage::OperationResultbackend后端连接句柄。key要删除的键。返回值操作状态与可选错误字符串键不存在时返回Storage::KEY_NOT_FOUND。3. 支撑类型BackendOptions、PutArgs 与 OperationResult3.1 Storage::BackendOptions后端连接配置定义于 scripts/base/frameworks/storage/main.zeek第 13–21 行是传给open_backend的基础配置记录后端插件可 redef 追加字段字段类型默认值说明serializerStorage::SerializerenumStorage::STORAGE_SERIALIZER_JSON用于转换 Zeek 数据的序列化器forced_syncboolStorage::default_forced_sync默认F是否强制进入同步模式设为T后即便调用异步函数也会走同步路径通常只在测试时使用其中default_forced_sync是可 redef 的全局选项默认F。加载具体后端策略后该记录会扩展字段例如加载policy/frameworks/storage/backend/sqlite后新增sqlite: Storage::Backend::SQLite::Options含database_path、table_name等加载 Redis 策略后新增redis: Storage::Backend::Redis::Options详见 doc/scripts/base/frameworks/storage/main.zeek.rst。框架同时提供可 redef 的Storage::latency_metric_boundsvector of double默认[0.001, 0.01, 0.1, 1.0]用于定义操作时延指标的直方图分桶单位秒。3.2 Storage::PutArgsput 的参数载体字段类型默认值说明keyany—存储所用的键valueany—与该键关联的值overwriteboolT键已存在时是否覆盖旧值expire_timeinterval0sec条目自动过期并被后端移除的时间0sec表示永不过期3.3 Storage::OperationResult统一返回结构定义于 scripts/base/init-bare.zeek第 6814–6826 行type OperationResult: record { code: ReturnCode; # 后端可 redef 的返回码 error_str: string optional; # 失败时设置非 SUCCESS 时应存在 value: any optional; # get 返回命中值open_backend 返回后端句柄 };code字段取自Storage::ReturnCode枚举仓库内置以下取值返回码含义SUCCESS操作成功VAL_TYPE_MISMATCH传入值的类型与打开后端时声明的值类型不符KEY_TYPE_MISMATCH传入键的类型与打开后端时声明的键类型不符NOT_CONNECTED后端未连接TIMEOUT操作超时CONNECTION_LOST后端连接意外丢失OPERATION_FAILED通用操作失败KEY_NOT_FOUND键在后端中不存在KEY_EXISTS待覆盖的键已存在CONNECTION_FAILED连接建立失败区别于已建立后丢失DISCONNECTION_FAILED断开失败INITIALIZATION_FAILED初始化失败IN_PROGRESS异步操作正在等待结果由异步操作返回ReturnCode带redef后端可追加自定义状态码。注意并非所有返回码对所有操作都合法。4. 源码级剖析异步函数如何分派阅读 scripts/base/frameworks/storage/async.zeek 第 81–126 行可以看到Storage::Async的每个公开函数并非直接发起异步请求而是先检查forced_sync状态再分派function open_backend(btype: Storage::Backend, options: Storage::BackendOptions, key_type: any, val_type: any): Storage::OperationResult { if ( options$forced_sync ) return Storage::Sync::__open_backend(btype, options, key_type, val_type); else return Storage::Async::__open_backend(btype, options, key_type, val_type); }close_backend、put、get、erase四个函数则统一以Storage::is_forced_sync(backend)判断分派方向例如function get(backend: opaque of Storage::BackendHandle, key: any) : Storage::OperationResult { if ( Storage::is_forced_sync(backend) ) return Storage::Sync::__get(backend, key); else return Storage::Async::__get(backend, key); }Storage::is_forced_sync与Storage::is_open是 C 内建函数声明在 src/storage/storage.bifis_forced_sync在句柄无效时返回F否则返回句柄所指向后端对象的IsForcedSync()结果。由此可以推断forced_sync是逐连接生效的open_backend依据BackendOptions$forced_sync决定该连接进入同步模式同一 Zeek 进程内可同时存在同步与异步后端句柄异步与同步共享同一套参数/返回结构模式切换对上层脚本透明代价仅是阻塞行为不同。另一个重要行为来自框架文档 doc/frameworks/storage.rst当用-r参数离线读取 pcap 时所有后端内部都以同步方式工作以保证 Zeek 的定时器机制正确运转。此时异步函数仍必须写在when中但底层会被转换为同步调用。5. 实战示例基于仓库测试用例的异步读写仓库的 btest 测试 testing/btest/scripts/base/frameworks/storage/sqlite/basic.zeek 完整演示了Storage::Async的open_backend→put→get→close_backend全链路且每个异步调用都嵌套在when中并带timeout兜底。下面是提取并整理的可运行示例load base/frameworks/storage/async load policy/frameworks/storage/backend/sqlite load base/frameworks/telemetry redef exit_only_after_terminate T; global b : opaque of Storage::BackendHandle; event Storage::backend_opened(tag: Storage::Backend, config: any) { print Storage::backend_opened, tag, config; } event zeek_init() { # 配置 SQLite 后端数据库文件与表名 local opts: Storage::BackendOptions; opts$serializer Storage::STORAGE_SERIALIZER_JSON; opts$sqlite [ $database_pathtest.sqlite, $table_nametesting ]; local key key1234; local value value5678; # 异步打开后端注意必须放在 when 条件中 when [opts, key, value] ( local open_res Storage::Async::open_backend( Storage::STORAGE_BACKEND_SQLITE, opts, string, string) ) { print open result, open_res; b open_res$value; when [key, value] ( local put_res Storage::Async::put(b, [ $keykey, $valuevalue ]) ) { print put result, put_res; when [key, value] ( local get_res Storage::Async::get(b, key) ) { print get result, get_res; if ( get_res$code Storage::SUCCESS get_res?$value ) print get result same as inserted, value ( get_res$value as string ); } timeout 5sec { print get request timed out; terminate(); } } timeout 5sec { print put request timed out; terminate(); } } timeout 5sec { print open request timed out; terminate(); } }要点归纳when是异步 API 的强制要求文档与源码均明确must be called via awhencondition or an error will be returned必须通过when条件调用否则返回错误。when右侧的局部声明如open_res在条件满足后自动可用key_type/val_type严格校验示例中声明键、值均为string后续put/get/erase传入其他类型会触发Storage::KEY_TYPE_MISMATCH或Storage::VAL_TYPE_MISMATCHget返回值需按声明类型转换OperationResult$value是any示例中通过get_res$value as string转回原类型并比较每个异步调用都应配timeout一旦后端无响应如连接丢失when的timeout 5sec分支会被触发避免脚本悬挂。exit_only_after_terminate T确保脚本直到显式terminate()才退出close_backend同样异步示例事件print_metrics_and_close()中再次用when包裹Storage::Async::close_backend(b)成功后再terminate()。另一个测试 testing/btest/scripts/base/frameworks/storage/sqlite/basic-reading-pcap.zeek 展示了混合用法用Storage::Sync::open_backend打开连接随后对同一句柄调用Storage::Async::put/Storage::Async::get最后用Storage::Sync::close_backend关闭——说明同步句柄与异步操作可以混用只要后端连接本身有效异步函数可作用在任何句柄上其is_forced_sync决定实际执行路径。6. 使用异步存储框架的注意事项综合框架文档 doc/frameworks/storage.rst 与源码实践中有以下几点约束后端与序列化器插件Zeek 默认提供 Redis需系统安装hiredis≥ 1.1.0Redis 服务端 ≥ 6.2.0与 SQLite 两个后端以及 JSON 序列化器Storage::STORAGE_SERIALIZER_JSON默认启用。切换后端只需更换btype标签与对应 options 记录脚本层 API 保持一致SQLite 的 WAL 限制SQLite 后端默认 pragma 将journal_mode设为WAL该模式不适用于网络文件系统——数据库文件必须位于所有打开它的 Zeek 进程同一台机器上若使用:memory:内存库数据不会在节点间同步每个进程持有独立数据库backend_lost的双重语义该事件在主动close_backend成功与连接意外丢失时都会被抛出脚本应据此实现重连逻辑forced_sync仅建议测试使用BackendOptions$forced_sync T会让所有操作包括异步 API走同步路径main.zeek注释明确 This should generally only be set toTduring testing通常仅在测试时设为T仓库中的redis/forced-sync.zeek、redis/async-reading-pcap.zeek等测试即覆盖此类场景同步/异步 API 二选一装载若脚本只使用同步 API可load base/frameworks/storage/sync两者同时装载亦无冲突因为Storage::Async在forced_sync时会调用Storage::Sync::__*反之亦然二者互为补充。7. 总结Storage::Async是 Zeek storage framework 的异步操作入口五个函数open_backend、close_backend、put、get、erase覆盖了后端生命周期管理与键值数据读写的全部场景。其核心设计包括统一返回结构Storage::OperationResult与后端可扩展的Storage::ReturnCode枚举when条件驱动的非阻塞调用模型配合timeout分支保证健壮性forced_sync双层分派机制脚本层先按连接状态决定走同步还是异步内建实现且-r读 pcap 时后端内部一律同步化类型即契约打开后端时声明的key_type/val_type会在所有后续操作中被严格校验。如需继续深入可查阅仓库中的 storage framework 框架文档、Storage 命名空间 API 文档、Storage::Sync 模块文档以及 storage 的 C 接口声明 与 SQLite 后端测试用例将异步存储能力接入自己的 Zeek 策略脚本。赞分享网络安全网络IDS【免费下载链接】zeekZeek is a powerful network analysis framework that is much different from the typical IDS you may know.项目地址https://gitcode.com/gh_mirrors/ze/zeek点击查看免费下载相关推荐Notion Avatar性能优化终极指南图片压缩、懒加载与PWA应用Notion Avatar性能优化终极指南图片压缩、懒加载与PWA应用 Notion Avatar Maker是一款强大的在线Notion风格头像生成工具它StatsD 对接 Graphite 配置完全指南Storage Schemas 与 Storage Aggregation 实战详解StatsD 对接 Graphite 配置完全指南Storage Schemas 与 Storage Aggregation 实战详解 本指南以 statsd可观测性指标监控Zeek Storage 框架同步存储接口详解Storage::Sync 的 open/close/put/get/erase 全解析Zeek Storage 框架同步存储接口详解Storage::Sync 的 open/close/put/get/erase 全解析 本篇技术指南围绕 Ze网络安全网络IDS上一篇戴森球计划蓝图库3000工厂设计让你的星际帝国建设效率翻倍下一篇aider 安装实战用 aider-install 一键搭建隔离环境并跑通你的第一个 AI 结对编程会话创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考