基于Portal的NJet模拟环境

1. 功能描述

作为开发人员,经常碰到的问题是代码开发、测试都是好的,但在客户现场/生产环境,总是出各种各样的问题。这种问题,有可能是实现的逻辑,但更多的情况是现场人员的配置问题导致。因此开发人员需要一个和现场完全一致的环境,进行现场的故障复现,配置验证。

NJet作为应用引擎,应用场景复杂,配置灵活,当然也面临此类问题。为了快速模拟 NJet 配置,验证整条业务链路是否通畅,同时检验系统在高压、大配置数据场景下的承载能力,并确认证书、限流等关键机制是否生效,NJet的模拟环境应运而生。我们期望通过该环境:

  • 自动构建、完全模拟客户的网络环境拓扑
  • 可视化验证客户的配置有效性
  • 可进行批量/单独的功能测试
  • 能够进行域名解析,证书校验,客户端地址等模拟,辅助功能验证

同时,出于简化GUI管理的目的,该模拟应用利用NJet存在的Portal能力,避免了相关的认证授权的开发工作。

2. NJet模拟应用的安装

随NJet4.0发布,NJet发布了模拟应用的安装包,因此需首先安装Portal安装包,在Portal部署完成后,通过GUI安装模拟应用

2.1 安装njet

njet4.0.1.0安装包下载链接获取

安装njet4.0.1.0:

yum localinstall njet-4.0.1.0-1.el7.x86_64.rpm

2.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:  ALL
Caution

a. 部署应用前需要先删除apps,再进行部署
b. NJet部署要求运行在麒麟机器或CentOS 8系统上,其他机器目前暂不兼容

2.4 登录portal

用重新设置的密码登录 /portal

aa26.jpg aa26.jpg

添加新用户:在用户管理页面,选择新增

aa26.jpg aa26.jpg

增加用户组njet_group

aa28.jpg aa28.jpg

增加角色

aa29.jpg aa29.jpg

为用户njet 分配组:

aa30.jpg aa30.jpg

为用户组分配角色

aa31.jpg aa31.jpg

aa32.jpg aa32.jpg

添加simulate-app应用:

simulate-app_1.0.2.npk的获取:simulate-app_1.0.2.npk

在应用管理中,选择新增,添加获取的 simulate-app_1.0.2.npk, 并点击确认

aa33.jpg aa33.jpg

aa35.jpg aa35.jpg

模拟应用授权

aa36.jpg aa36.jpg aa37.jpg aa37.jpg

模拟应用配置
为支持网络拓扑模拟,以及调用可示化,模拟应用需要特定的配置,如下。请维持如下

aa38.jpg aa38.jpg

配置项 类型 说明
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应用后,就可以看到模拟应用了

aa39.jpg aa39.jpg

3.功能展示

3.1 配置导入

  • 功能模拟依赖于导入配置文件,目前配置文件需要使用json格式,目前需要手工把nginx格式的配置文件转换为json,paste或上传,在下个版本中,将直接支持nginx.conf格式的配置
  • 除导入外,模拟应用中也提供了多种示例配置,供参考
  • 除配置文件外,还可以配置模拟访问的特定的client ip,供特定的业务模拟使用

如下图所显示,可以看到页面中有很多实例配置,可自由切换,也可以导入JSON文件的配置

aa40.jpg aa40.jpg

3.2 拓扑展示

如下图点击 示例配置1 (无证书)可直接进进入模拟页面,该页面直接生成了包括客户端->proxy->应用服务的网络拓扑,并详细描述proxy层面的业务配置,需着重说明的是,模拟环境中显示的IP地址,完全模拟了实际客户环境的地址。如下图所显示,展示了一个具备两个server的proxy层配置(test.backenda.com和test.backendb.com)

aa41.jpg aa41.jpg

3.3 业务流程验证

在模拟环境中,下侧为web terminal,可以输入特定的命令,单条或批量发送HTTP请求,验证配置的正确性。目前内置了curl和wrk命令,前者进行单条的功能测试,后者进行批量的测试

  • 单条测试 如下图所显示,单条测试中,在GUI界面可以看到完整的执行路径(图上的虚线涉及的点),比如通过curl发了一条到testbackenda.com的请求,可以从图上直观的看到,请求直接由proxy层的path “/”处理了,没有转发到后端的应用服务

aa42.png aa42.png

3.4 批量测试

为了验证配置中某些特定的功能,如限流等,可以在web terminal输入wrk命令进行压测(批量命令的执行路径不会更新到GUI中)

aa43.png aa43.png

3.5 通过导入证书,可以完整的模拟HTTPS proxy能力

3.5.1 rsa 证书

aa46.jpg aa46.jpg

上传证书

aa45.jpg aa45.jpg

rsa 测试:

aa47.png aa47.png

3.5.2 国密证书

上传国密证书

国密测试

3.6 完整的模拟历史,供配置分析

aa48.jpg aa48.jpg

3.7 Web terminal的实现帮助

aa50.jpg aa50.jpg

3.8 客户端ip地址的任意更换,支持特定的算法

aa61.jpg aa61.jpg

3.9 超大规模的模拟配置支持(可支持多大512个server,1000个location,512个后端服务)

aa63.png aa63.png

aa64.png aa64.png

参考说明

  1. 目前只支持json格式的配置导入,json格式请参考,json配置文件支持
  2. 依赖NJet 4.0.0
  3. 出于安全考虑,NJet安装后,需要修改 agw_admin密码才能进行portal应用的安装
  4. 在下一版本中,将直接支持nginx.conf格式的导入,从而服务于nginx向NJet的迁移