基于Portal的NJet模拟环境
1. 功能描述
作为开发人员,经常碰到的问题是代码开发、测试都是好的,但在客户现场/生产环境,总是出各种各样的问题。这种问题,有可能是实现的逻辑,但更多的情况是现场人员的配置问题导致。因此开发人员需要一个和现场完全一致的环境,进行现场的故障复现,配置验证。
NJet作为应用引擎,应用场景复杂,配置灵活,当然也面临此类问题。为了快速模拟 NJet 配置,验证整条业务链路是否通畅,同时检验系统在高压、大配置数据场景下的承载能力,并确认证书、限流等关键机制是否生效,NJet的模拟环境应运而生。我们期望通过该环境:
- 自动构建、完全模拟客户的网络环境拓扑
- 可视化验证客户的配置有效性
- 可进行批量/单独的功能测试
- 能够进行域名解析,证书校验,客户端地址等模拟,辅助功能验证
同时,出于简化GUI管理的目的,该模拟应用利用NJet存在的Portal能力,避免了相关的认证授权的开发工作。
2. NJet模拟应用的安装
随NJet4.0发布,NJet发布了模拟应用的安装包,因此需首先安装Portal安装包,在Portal部署完成后,通过GUI安装模拟应用
2.1 安装njet
安装njet4.0.1.0:
yum localinstall njet-4.0.1.0-1.el7.x86_64.rpm2.2 配置
njet.conf:
worker_processes auto;
cluster_name njet;
node_name node1;
error_log logs/error.log info;
helper ctrl modules/njt_helper_ctrl_module.so conf/njet_ctrl.conf;
helper broker modules/njt_helper_broker_module.so;
load_module modules/njt_agent_dynlog_module.so;
load_module modules/njt_dyn_ssl_module.so;
load_module modules/njt_http_vtsc_module.so;
load_module modules/njt_http_location_module.so;
load_module modules/njt_http_lua_module.so;
load_module modules/njt_http_dyn_upstream_module.so;
load_module modules/njt_http_dyn_server_module.so;
load_module modules/njt_http_token_sync_module.so;
load_module modules/njt_http_upstream_member_module.so;
load_module modules/njt_http_dyn_lua_module.so;
load_module modules/njt_http_mqtt_module.so;
load_module modules/njt_stream_ws_module.so;
load_module modules/njt_stream_proto_server_module.so;
load_module modules/njt_openapi_util_module.so;
events {
worker_connections 1024;
}
shared_slab_pool_size 100m;
http {
token_sync zone=token:4M sync_time=5s clean_time=10s;
dyn_kv_conf conf/iot-work.conf;
include mime.types;
access_log off;
vhost_traffic_status_zone;
lua_package_path "$prefix/lualib/lib/?.lua;$prefix/modules/?.lua;$prefix/apps/?.lua;;";
lua_package_cpath "$prefix/lualib/clib/?.so;;";
init_by_lua_block {
local _=require("lor.index")
local _=require("lsqlite3complete")
}
upstream mqtt_upstream {
mqtt_server 127.0.0.1:28083;
}
server {
listen 8080;
error_page 401 =302 /portal;
client_max_body_size 1000m;
location / {
#root html;
root apps/simulateApp/static;
}
location /icons/ {
alias /usr/local/njet/apps/__icons/;
try_files $uri =404;
}
location /v1/traces {
mqtt_topic /trace;
client_body_buffer_size 10M;
mqtt_pass mqtt_upstream;
}
location /ws2mqtt {
proxy_pass http://127.0.0.1:28082;
}
}
}
stream {
upstream up_broker {
server unix:/usr/local/njet/data/mosquitto.sock;
}
server {
listen 127.0.0.1:28083;
mqtt_pass up_broker;
mqtt_proxy_next_upstream on;
mqtt_proxy_next_upstream_tries 3;
}
server {
listen 28082;
proto_server on;
proto_buffer_size 1024k;
proto_server_idle_timeout 600;
proto_server_code_file "modules/njt_stream_ws2mqtt_tcc_module.so";
proto_pass up_broker;
#proxy_xxx (设置证书)
}
}njet_ctrl.conf:
load_module modules/njt_http_sendmsg_module.so;
load_module modules/njt_ctrl_config_api_module.so;
load_module modules/njt_helper_health_check_module.so;
load_module modules/njt_http_upstream_api_module.so;
load_module modules/njt_http_location_api_module.so;
load_module modules/njt_doc_module.so;
load_module modules/njt_http_vtsd_module.so;
load_module modules/njt_http_lua_module.so;
load_module modules/njt_http_dyn_upstream_module.so;
load_module modules/njt_http_dyn_upstream_api_module.so;
load_module modules/njt_http_dyn_server_api_module.so;
load_module modules/njt_http_upload_module.so;
error_log logs/error_ctrl.log error;
events {
worker_connections 1024;
}
http {
dyn_kv_conf conf/ctrl_kv.conf;
lua_package_path "$prefix/lualib/lib/?.lua;$prefix/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 {
client_max_body_size 1000m;
listen 8081;
location / {
return 200 "njet control panel\n";
}
location /api {
dyn_module_api;
}
location /doc {
doc_api;
}
location /metrics {
vhost_traffic_status_display;
vhost_traffic_status_display_format html;
}
location /api_gateway {
access_by_lua_block {
local ac=require("api_gateway.access.control")
local access=ac.new("/api_gateway")
access:check()
}
content_by_lua_block {
local api_gateway=require("api_gateway")
api_gateway.main()
}
}
}
}2.3 portal 获取和安装
下载portal_1.0.2_noarch.npk 和ssh_remote_mod.so
拷贝 ssh_remote_mod.so
sudo cp ssh_remote_mod.so /usr/local/njet/lualib/clib/管理员账号 agw_admin 在安装njet 时会生成一个随机密码,使用密码重置工具进行密码的设置
sudo /usr/local/njet/sbin/agw_passwd /usr/local/njet/apigw_data/api_gateway.db 密码重启 njet
sudo systemctl stop njet
sudo systemctl start njet 将下载后的 portal_1.0.2_noarch.npk 文件上传到 njet 主机上,并且主机上安装 curl 及 jq 命令行工具
NJET_SITE="http://localhost:8081"
PORTAL_FILE=$(curl -k -s -F "file=@portal_1.0.2_noarch.npk" "$NJET_SITE/api/v1/upload" |jq -r '.file')
echo $PORTAL_FILE
TOKEN=$(curl -k -X POST -d '{"login_data":{"username": "agw_admin", "password": "123456"}}' -s "$NJET_SITE/api_gateway/auth/login" | jq -r '.token')
echo $TOKEN
curl -X 'POST' \
"$NJET_SITE/api_gateway/deploy/app" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"uploaded_file\": \"$PORTAL_FILE\"}"配置sudo权限
sudo visudo
添加如下配置
njet ALL=(ALL:ALL) NOPASSWD: ALLCaution
a. 部署应用前需要先删除apps,再进行部署
b. NJet部署要求运行在麒麟机器或CentOS 8系统上,其他机器目前暂不兼容
2.4 登录portal
用重新设置的密码登录 /portal
添加新用户:在用户管理页面,选择新增
增加用户组njet_group
增加角色
为用户njet 分配组:
为用户组分配角色
添加simulate-app应用:
simulate-app_1.0.2.npk的获取:simulate-app_1.0.2.npk
在应用管理中,选择新增,添加获取的 simulate-app_1.0.2.npk, 并点击确认
模拟应用授权
模拟应用配置
为支持网络拓扑模拟,以及调用可示化,模拟应用需要特定的配置,如下。请维持如下
| 配置项 | 类型 | 说明 |
|---|---|---|
| RUN USER | String | 虚拟环境启动的njet进程的用户 |
| RUN GROUP | String | 虚拟环境启动的njet进程的用户组 |
| vethHostIP | String | 虚拟环境 otelcol 需要往 host 环境发数据,因此需要配置veth 对, veth对的 host 端地址 |
| vethProxyIP | String | 虚拟环境 otelcol 需要往 host 环境发数据,因此需要配置veth 对, veth对的 proxy 端地址 |
| otelHttp2MqttUrl | String | 运行Portal 应用的NJet 中配置的 opentelemtry http2mqtt url 地址,Url 中的协议、端口及路径都是 NJet中对应的配置项,Url 中的 IP 是 vethHostIP |
登录portal应用后,就可以看到模拟应用了
3.功能展示
3.1 配置导入
- 功能模拟依赖于导入配置文件,目前配置文件需要使用json格式,目前需要手工把nginx格式的配置文件转换为json,paste或上传,在下个版本中,将直接支持nginx.conf格式的配置
- 除导入外,模拟应用中也提供了多种示例配置,供参考
- 除配置文件外,还可以配置模拟访问的特定的client ip,供特定的业务模拟使用
如下图所显示,可以看到页面中有很多实例配置,可自由切换,也可以导入JSON文件的配置
3.2 拓扑展示
如下图点击 示例配置1 (无证书)可直接进进入模拟页面,该页面直接生成了包括客户端->proxy->应用服务的网络拓扑,并详细描述proxy层面的业务配置,需着重说明的是,模拟环境中显示的IP地址,完全模拟了实际客户环境的地址。如下图所显示,展示了一个具备两个server的proxy层配置(test.backenda.com和test.backendb.com)
3.3 业务流程验证
在模拟环境中,下侧为web terminal,可以输入特定的命令,单条或批量发送HTTP请求,验证配置的正确性。目前内置了curl和wrk命令,前者进行单条的功能测试,后者进行批量的测试
- 单条测试 如下图所显示,单条测试中,在GUI界面可以看到完整的执行路径(图上的虚线涉及的点),比如通过curl发了一条到testbackenda.com的请求,可以从图上直观的看到,请求直接由proxy层的path “/”处理了,没有转发到后端的应用服务
3.4 批量测试
为了验证配置中某些特定的功能,如限流等,可以在web terminal输入wrk命令进行压测(批量命令的执行路径不会更新到GUI中)
3.5 通过导入证书,可以完整的模拟HTTPS proxy能力
3.5.1 rsa 证书
上传证书
rsa 测试:
3.5.2 国密证书
国密测试
3.6 完整的模拟历史,供配置分析
3.7 Web terminal的实现帮助
3.8 客户端ip地址的任意更换,支持特定的算法
3.9 超大规模的模拟配置支持(可支持多大512个server,1000个location,512个后端服务)
参考说明
- 目前只支持json格式的配置导入,json格式请参考,json配置文件支持
- 依赖NJet 4.0.0
- 出于安全考虑,NJet安装后,需要修改 agw_admin密码才能进行portal应用的安装
- 在下一版本中,将直接支持nginx.conf格式的导入,从而服务于nginx向NJet的迁移


























