NGINX 向云原生演进,All inOpenNJet
1. 特性介绍
OpenNJet 实现了可持久化的键值存储(key-value store)功能,并提供了相应的API对键值进行操作。基于KV Store提供的能力,可以用于如下场景:
- 模块动态配置信息的持久化
- OpenNJet不同模块间运行状态信息的共享
- 外部系统对NJet运行模块的动态参数调整
例如OpenNJet 目前提供的动态Worker数目调整功能,就是通过设置特定的KEY值,以此来触发Master 进程对运行Worker进程的管理。
2. 实现方案
开源社区已经有大量的中间件,如Redis, Etcd,这些中间件都可以用来做键值存储的数据库, 但这样不仅需要OpenNJet中有相应模块与其进行交互,并且部署时增加了外部组件的依赖。
OpenNJet KV Store 的实现上,使用了轻量级的内存数据库 LMDB。LMDB是基于内存映射的,效率高,并且访问简单,不需要单独的数据管理进程,只要在访问代码里引用LMDB库。LMDB的文件结构简单,包含一个数据文件和一个锁文件,通过锁控制来实现事务隔离,LMDB文件可以同时由多个进程打开。使用该方案,整体架构简单清晰。
OpenNJet 与其它负载均衡产品KV Store 功能的比较:
OpenNJet | nginx OSS | nginx Plus | APISIX | |
---|---|---|---|---|
是否支持 | 支持 | 无内置KV Store | 支持 | 支持 |
实现方式 | LMDB | / | 共享内存 | Etcd |
使用方式 | Restful, Lua, C API | / | Restful, Njs | Restful, Lua |
是否收费 | 开源免费 | / | 付费使用 | 开源免费 |
3. 使用说明
3.1 C API
使用C开发OpenNJet的扩展模块时,可以使用OpenNJet提供的kv 能力,对kvstore进行操作。
以数据面的模块为例,模块中需要包含OpenNJet源码中的头文件:
#include
int njt_db_kv_get(njt_str_t *key, njt_str_t *value);
int njt_db_kv_set(njt_str_t *key, njt_str_t *value);
int njt_db_kv_del(njt_str_t *key);
调用样例代码如下:
static int kv_get_example()
{
njt_str_t lmdb_key = njt_string("test_key");
njt_str_t lmdb_value;
njt_int_t ok;
lmdb_value.len=0;
lmdb_value.data=NULL;
ok = njt_db_kv_get(&lmdb_key, &lmdb_value);
if (ok == NJT_OK)
{
...
}
return NJT_OK;
}
3.2 Lua 方式
OpenNJet 提供了封装后的Lua kv store API,在Lua 中引用”njt.kv” Lua 库, 之后使用Lua 函数对kv store 进行操作,函数包括:db_kv_get, db_kv_set, db_kv_del。
测试代码如下:
location /lua_kv_test {
content_by_lua_block {
local kv = require("njt.kv")
local args, err = njt.req.get_uri_args()
local key = args["key"]
local rc,msg = kv.db_kv_get(key)
if rc == 0 then
njt.say("old value is: "..msg)
else
njt.say("there is no such key in kv")
end
local newValue = key .."_"..tostring(os.time())
rc = kv.db_kv_set(key, newValue)
if rc == 0 then
njt.say("set to new value: "..newValue)
else
njt.say("error occuried")
end
}
}
location /lua_kv_del {
content_by_lua_block {
local kv=require("njt.kv")
local args, err= njt.req.get_uri_args()
local key=args["key"]
local _, msg= kv.db_kv_del(key)
njt.say(msg)
}
}
3.3 Restful 方式
使用官网提供的RPM 包安装后,生成的控制面njet_ctrl配置中,已包含一个可以用来设置kv值的location
location /kv {
dyn_sendmsg_kv;
}
可以使用Restful 的方式,GET,POST, DELETE 来对键值进行操作。
使用控制面提供的Restful 接口在设置键值时,将在key前添加 “kv_http_” 的前缀。如果使用C或Lua API,与Restful 接口设置的键值需要互操作的场景下, 在C或Lua API调用对应函数时,需要自行添加”kv_http_” 的前缀。
OpenNJet 最早是基于 NGINX1.19 基础 fork 并独立演进,具有高性能、稳定、易扩展的特点,同时也解决了 NGINX 长期存在的难于动态配置、管理功能影响业务等问题。
邮件组 官网