写点什么

即将发布:NJet 共享内存指标展示及动态扩展

作者:通明湖
  • 2025-02-25
    北京
  • 本文字数:4198 字

    阅读完需:约 14 分钟

nginx 向云原生演进,All in OpenNJet

简介


共享内存是 NJet 实现高性能和高并发处理的关键机制之一。它允许多个工作进程共享数据,减少重复计算和资源消耗,同时支持复杂的业务逻辑(如限流、负载均衡、会话管理等)。通过合理使用共享内存,可以显著提升 NJet 的性能和可靠性。从 NJet3.0 开始,NJet 实现了对动态共享内存的支持,解决了关键的资源分配无法应对业务弹性变化的关键痛点。目前,NJet 的动态共享内存功能有了新的增强,新增的主要功能有两个:


支持对共享内存的使用情况进行统计、展示,目前支持 json 格式,html 格式及 prometheus 格式。同时还展示了 NJet 中的 ctrl 进程及各个 worker 进程的内存及 CPU 使用情况。


支持通过 API 为每个共享内存池配置自动扩展属性,在配置了动态共享内存后,设置了属性的共享内存池可以自动扩展。


目前,此功能在开发分支上实现,后续会合并到主分支上发布。如想试用,可自行从 gitee 平台上下载开发分支进行编译,试用。


共享内存指标展示


要展示共享内存的使用情况,需要对 NJet 的 helper 配置文件(如 njet_ctrl.conf)修改,增加黄色标注的配置。配置动态共享内存的命令可参考 gitee 上的使用手册。


Bash  \# conf/njet_ctrl.conf  load_module /usr/local/njet/modules/njt_http_sendmsg_module.so;  load_module /usr/local/njet/modules/njt_ctrl_config_api_module.so;  load_module /usr/local/njet/modules/njt_helper_health_check_module.so;  load_module /usr/local/njet/modules/njt_http_upstream_api_module.so;  load_module /usr/local/njet/modules/njt_http_location_api_module.so;  load_module /usr/local/njet/modules/njt_doc_module.so;  load_module /usr/local/njet/modules/njt_http_vtsd_module.so;  load_module /usr/local/njet/modules/njt_http_shm_status_module.so;  load_module modules/njt_http_shm_api_module.so;  <br/>error_log logs/error_ctrl.log error;  <br/>events {  worker_connections 1024;  }  <br/>http {  \# dyn_kv_conf conf/ctrl_kv.conf;  \# lua_package_path "$prefix/lualib/lib/?.lua;/usr/local/njet/modules/?.lua;;";  \# lua_package_cpath "$prefix/lualib/clib/?.so;;";  \# init_by_lua_block {  \# local \_=require("lor.index")  \# local \_=require("lsqlite3complete")  \# }  include mime.types;  access_log off;  server {  listen 8089;  <br/>... ...  location /api {  dyn_module_api;  <br/>}  <br/><br/>location /shm {  shm_status_display;  }  }  }  
复制代码

通过上面的配置,在运行后就可以通过浏览器查看共享内存的使用情况了。下面给出的地址都是参考上述配置。具体展示的指标有:

全局统计:包括动态 zone 和静态 zone;

zone 一级:包括 size, 这里的 size 是一个 pool 的大小, pool 数目等;

pool 一级:包括总页数和已用页数;

slot 一级:这一级指的是小于半个页面(4k/2 = 2k)大小的内存分配情况,njet 使用单独的数据结构来管理这类内存的分配;

Worker 的内存及 CPU 使用统计

JSON 格式

访问地址:http://127.0.0.1:8089/shm/format/json

PROMETHEUS 格式

访问地址:http://127.0.0.1:8089/shm/format/prometheus

这种格式主要供系统资源监控使用,所以没有给出上面说到的 slot 一级的指标和 pool 一级的指标。

2

HTML 格式

访问地址:http://127.0.0.1:8089/shm/format/html

这种模式下,指标以表格形式输出,并且会自动更新。

共享内存动态扩展设置

这次更新中,还为每一个共享内存的 zone 增加了一个自动扩展(autoscale)的属性。这个属性可以通过 NJet 的控制 API 来实现。要使用此功能,需要在 njet_ctrl.conf 中增加下面的配置。

Bash  load_module modules/njt_http_shm_api_module.so;
复制代码

访问地址:http://127.0.0.1:8089/doc/swagger/

点击红线内的接口,跳转到下面的页面

通过对应的接口可以设置/取消/查询对应 zoneName 的共享内存的可扩展属性。其中 typeName 的取值有两个:

static 对应静态共享内存,即 html 格式中 static_zones 中的列表;

dynamic 对应动态共享内存,即 html 格式中 static_zones 中的列表。

这些请求都可以通过 curl 向相应的接口发送请求来实现。如设置共享内存非自动扩展属性,发送

Bash  curl -X 'PUT' \\  '<http://127.0.0.1:8089/api/v1/shm/unset/dynamic/dyn_backend1>' \\  \-H 'accept: \*/\*'
复制代码

返回

Bash  {  "code": 0,  "msg": "successfully update zone status"  }
复制代码

查询共享内存自动扩展属性值,发送

Bash  curl -X 'GET' \\  '<http://127.0.0.1:8089/api/v1/shm/get/dynamic/dyn_backend1>' \\  \-H 'accept: application/json'
复制代码

返回

Bash  {  "code": 0,  "msg": "zone autoscale is unset"  }
复制代码

动态共享内存自动扩展示例

下面给出一个设置动态内存可扩展属性的例子,具体配置如下图,这是一个配置 lua 字典的例子,具体配置如下,其中

第 28 行定义了总的动态共享内存的大小为 100M;

第 31 行定义了一个静态共享内存,大小为 10M;

第 49 行定义的 location 中的 lua 块将接收到的数据保存到字典中(第 67 行)。

Bash  worker_processes auto;  <br/>cluster_name njet;  node_name node1;  <br/>error_log logs/error.log error;  <br/>helper ctrl /usr/local/njet/modules/[njt_helper_ctrl_module.so](http://njt_helper_ctrl_module.so) /usr/local/njet/conf/njet_ctrl.conf;  helper broker /usr/local/njet/modules/[njt_helper_broker_module.so](http://njt_helper_broker_module.so);  helper access_data /usr/local/njet/modules/[njt_helper_access_data_module.so](http://njt_helper_access_data_module.so) /usr/local/njet/conf/go  access.conf;  <br/>load_module /usr/local/njet/modules/[njt_http_split_clients_2_module.so](http://njt_http_split_clients_2_module.so);  load_module /usr/local/njet/modules/[njt_agent_dynlog_module.so](http://njt_agent_dynlog_module.so);  load_module /usr/local/njet/modules/[njt_http_dyn_bwlist_module.so](http://njt_http_dyn_bwlist_module.so);  load_module /usr/local/njet/modules/[njt_dyn_ssl_module.so](http://njt_dyn_ssl_module.so);  load_module /usr/local/njet/modules/[njt_http_vtsc_module.so](http://njt_http_vtsc_module.so);  load_module /usr/local/njet/modules/[njt_http_location_module.so](http://njt_http_location_module.so);  load_module /usr/local/njet/modules/[njt_http_access_log_zone_module.so](http://njt_http_access_log_zone_module.so);  load_module /usr/local/njet/modules/[njt_http_lua_module.so](http://njt_http_lua_module.so);  load_module modules/[njt_http_dyn_upstream_module.so](http://njt_http_dyn_upstream_module.so);  <br/><br/>events {  worker_connections 1024;  }  <br/>shared_slab_pool_size 100M;  <br/>http {  lua_shared_dict configuration_data 10M;  dyn_kv_conf conf/iot-work.conf;  include mime.types;  access_log off;  access_log_write_zone on;  vhost_traffic_status_zone;  access_log_zone log_zone 100m;  \# access_log_zone_ignore_ip [127.0.0.1](http://127.0.0.1);  access_log_zone_valid 3;  <br/>#lua_package_path "$prefix/lualib/lib/?.lua;/usr/local/njet/modules/?.lua;$prefix/apps/?.lua;;"  ;  \# lua_package_cpath "$prefix/lualib/clib/?.so;;";  server {  listen 8080;  location / {  root html;  }  location /set_key {  \# Set content type to text/plain for simplicity  default_type text/plain;  <br/>\# Use Lua code to set a key into the shared dictionary  content_by_lua_block {  \-- Get the 'key' parameter from the URL  local key = ngx.var.arg_key  \-- Get the 'value' parameter from the URL  local value = ngx.var.arg_value  <br/>if not key or not value then  ngx.say("Missing key or value parameter")  return  end  <br/>\-- Store the key-value pair in the shared dictionary  local dict = ngx.shared.configuration_data  local success, err, forcible = dict:set(key, value)  <br/>if success then  ngx.say("Key '" .. key .. "' set to '" .. value .. "' successfully")  else  ngx.say("Failed to set key: ", err)  end  }  }  <br/>location /get_key {  default_type text/plain;  content_by_lua_block {  local key = ngx.var.arg_key  if not key then  ngx.say("Key parameter is missing")  return  end  <br/>local dict = ngx.shared.configuration_data  local value, flags, stale = dict:get(key)  <br/>if value then  ngx.say("Value for key '" .. key .. "' is: " .. value)  else  ngx.say("Key '" .. key .. "' not found")  end  }  }  }  }
复制代码

可通过下面的脚本持续向字典中增加数据

Bash  for i in {1..20000}; do curl -s "localhost:8080/set_key?key=a_$i&value=b_$i" > /dev/null;done;
复制代码

在没给 configuration_data 设置可扩展属性前,测试中可以看到内存池已经满。

在设置 configuration_data 设置可扩展属性后,请求在内存池满了后会自动扩展。 从图中看到,configuration_data 中的内存池已经扩展为 3 个。这项功能的一种使用场景是

为整个系统配置一个合适的总的动态内存空间大小;

使用 prometheus 接口定期采集系统中共享内存的使用情况;

当发现有共享内存空间的使用率超过预设的阈值时,发出告警;

根据 zone 的具体使用方式,确定是否需要设置动态扩展。

其它说明

当前功能将在 25 年 Q1 末的 NJet3.3 发布时支持,敬请期待


NJet 应用引擎通过内核重构实现了独特的运行时 动态配置加载 能力,是 新一代高性能 Web 应用引擎 。NJet 拥有高性能数据面处理能力,将集群、高可用、主动健康检查、声明式 API 等多种辅助功能,通过 NJet 独特的副驾驶 CoPilot 服务框架调度,从而方便功能扩展,隔离管理 / 控制功能对数据面的影响,NJet 应用引擎性能超过 CNCF 推荐 Envoy 应用引擎的三倍。 


官网:https://njet.org.cn/ 

邮件组:https://njet.org.cn/mailman/listinfo

发布于: 刚刚阅读数: 3
用户头像

通明湖

关注

让应用永远在线! 2022-10-13 加入

持续科技创新,信创应用交付领域的排头兵

评论

发布
暂无评论
即将发布:NJet共享内存指标展示及动态扩展_通明湖_InfoQ写作社区