NJet Portal 应用门户管理介绍

NGINX 向云原生演进,All in OpenNJet

  1. 应用门户简介

NJet 应用引擎是基于 Nginx 的面向互联网和云原生应用提供的运行时组态服务程序,作为底层引擎,NJet 实现了NGINX 云原生功能增强、安全加固和代码重构,利用动态加载机制可以实现不同的产品形态,如Web服务器、流媒体服务器、负载均衡、代理(Proxy)、应用中间件、API网关、消息队列等产品形态等等。NJet使用现有的API Gateway及各动态配置模块提供的能力,实现了一个Portal管理模块。通过该模块,对外提供应用门户的功能,以此来简化应用的开发及部署过程。应用可以只专注于业务逻辑的实现,将通用的安装配置及权限认证功能统一交给NJet应用门户管理模块。逻辑架构如下图所示:

2. 应用部署流程

用户使用管理员账号登录Portal门户,上传应用,添加用户/组/角色,最后进行应用的授权。完成上述操作后,使用普通用户账号登录门户,即可使用应用。

a. 管理员登录

在部署包含Portal 管理模块的环境上,使用api gateway的管理员账号登录后,将显示Portal 的管理界面,在该界面中可以进行应用的部署,及相关的授权。

b. 上传应用

应用管理中点击"新增",选择Portal 应用的相应npk 文件(应用的结构在后续章节进行说明)。点击确认后,Portal管理模块将自动创建应用需要的Location/Upstream, 由于使用了NJet的动态配置功能,所有的改动将实时生效,不需要重启或重加载NJet。

应用如果需要连接第三方组件,门户管理模块也提供了通用组件的配置能力。

c. 创建访问应用需要的用户/组/角色

应用门户使用Api Gateway提供的授权能力,其模型是"用户->组->角色"的授权模型,一个用户可以归属于不同的用户组,一个用户组可以分配多个角色,API 授权将授权到角色上。

应用门户的 UI上可以对用户/组/角色及相互间的关系进行维护。

d. 对应用进行授权

在应用管理中,选择应用授权,对应用不同的访问路径可以授予不同的角色。

e. 普通用户登录

使用普通用户账号登录后,将显示应用一览页面,在改列表页面中点击对应的图标,将跳转至具体的应用中。

3. Portal 应用结构

使用Portal 管理模块部署的应用,需要使用Portal模块可以识别的格式进行目录规划及应用打包,文件类型是npk (NJet Package)。 典型的目录结构如下图所示:

  • META-INF 目录
    manifest.json: 应用的基本信息,包括入口地址,配置地址,及location / upstream 信息。
    图标文件: jpg 或 jpg 格式的文件
    app_openapi.json: openapi 3.0 格式的文件,其中path 支持 通配符*, 例如 /setting/*
    app_schema.json: 应用需要的组件配置项 (可选,非必须)
  • scripts 目录
    应用使用的脚本
  • static 目录
    静态页面,资源文件,javascript 脚本, css

manifest.json 示例

该文件中定了入口地址(entry_point), 应用配置地址(cfg_url), 及应用需要的 location, upstream servers, \proxy_pass。Location 中可以直接配置属性("__access_control": "true" ) 来标识该访问地址需要使用门户提供的用户授权功能。

bash 复制代码
{
  "manifest_version": "1.0.0",
  "app": {
    "name": "ollamaApp",
    "version": "1.0.0",
    "arch": "x86_64",
    "description": "Ollma Chat application",
    "icon_file": "ollama.jpg",
    "api_file": "app_openapi.json" 
  },
  "deployment": {
    "type": "location",
    "server_name": "",
    "entry_point": "/ollama-app/open/chat",
    "cfg_url": "/ollama-app/open/config",
    "locations": [
      {
        "path": "/ollama-app/conversation",
        "properties": {
          " content_by_lua_file": "${APP_PREFIX}/scripts/chat_api.lua"
        }
      },
      {
        "path": "/ollama-app/setting",
        "properties": {
          "__access_control": "true", 
          " content_by_lua_file": "${APP_PREFIX}/scripts/chat_api.lua"
        }
      },
      {
        "path": "/ollama-app/chat",
        "properties": {
          "access_by_lua_file": "${APP_PREFIX}/scripts/access.lua",  
           "proxy_set_header": [
            "Host 192.168.0.206",
            "Origin http://192.168.0.206"
          ],
          "proxy_pass": {
            "schema": "http",
            "servers": [
              {"server":"192.168.40.206:11434"}
            ],
            "url": "/api/chat"
          }
        }
      },
      {
        "path": "/ollama-app",
        "properties": {
          "__access_control": "true", 
          "alias": "${APP_PREFIX}/static/",
          "try_files": "$uri $uri/ /ollama-app/index.html"
        }
      }
    ]
  }
}

app_schema.json 示例

应用需要连接第三方组件时,组件的配置通过json文件描述配置项,门户管理模块将根据json内容动态生成配置页面。该配置使用 formily (阿里巴巴表单框架 formilyjs.org/)定义的格式。 以下示例文件为连接redis 组件时需提供的json文件。

css 复制代码
{
    "redis_host": {
        "type": "string",
        "x-component": "Input",
        "x-component-props": {
            "placeholder": "请输入ip地址"
        },
        "x-decorator": "Form.Item",
        "x-decorator-props": {
            "label": "Redis IP",
            "tooltip": "请输入ip地址"
        }
    },
    "redis_port": {
        "type": "number",
        "x-component": "InputNumber",
        "x-component-props": {
            "placeholder": "请输入端口号",
            "min": 0,
            "max": 65535
        },
        "x-decorator": "Form.Item",
        "x-decorator-props": {
            "label": "Redis Port",
            "tooltip": "请输入端口号"
        }
    },
    "redis_password": {
        "type": "string",
        "x-component": "Input.Password",
        "x-component-props": {
            "placeholder": "请输入 密码"
        },
        "x-decorator": "Form.Item",
        "x-decorator-props": {
            "label": "Redis密码",
            "tooltip": "请输入密码"
        }
    }
}

4. Demo 应用完整实例

a. 通过ftp 获取到 demo 应用包

地址: ftp.tmlake.com

目录: /OpenNjet/Software/v3.2.2-portal

文件: demo_app_1.0.2.npk

b. 使用默认管理员账号 agw_admin /****** 登录 /portal

c. 添加demo应用

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

成功后,应用管理页面将出现 demo 应用的条目

d. 为用户添加用户/组/角色

添加一个demo用户角色

添加一个demo用户组

为这个组分配角色

添加一个 user1 用户,并指定 domain 为 "demo"

为这个用户分配组

e. 编辑应用的授权

在应用管理列表中点击 demo 的授权

该应用只有一个访问地址,选择后点击授权,在弹出的窗口下拉框中选择"demoUserRole"

f. 使用刚创建的普通用户账号登录 /portal

应用列表中显示出我们刚刚部署的demo 应用

点击应用图标后,跳转到应用的页面

该demo应用只是简单的一些页面Tab, 展示的也只是一些测试数据

5. 后续改进

目前部署的应用有新版本需要升级时,需要在应用管理中删除应用后,重新上传。后续将继续优化门户管理模块,提供应用的版本管理及回滚功能。

6. 参考

a. 使用到的API

API Gateway: 用户/组/权限的增删改查,api group 创建,oas3.0 格式文档导入,应用部署接口
gitee.com/njet-rd/nje...

动态Location API: 动态添加及删除Location
gitee.com/njet-rd/nje...

动态Upstream API: 动态添加及删除 Upsteam
gitee.com/njet-rd/nje...\

b. Demo 应用包的下载

地址: ftp.tmlake.com \

目录: /OpenNjet/Software/v3.2.2-portal

文件: demo_app_1.0.2.npk

c. NJet版本及Portal 获取及安装

NJet 版本需要 > 3.2.2

Portal 门户管理模块获取:

地址: ftp.tmlake.com

目录: /OpenNjet/Software/v3.2.2-portal/

文件: portal_1.0.2.npk , ssh_remote_mod.so

Portal 门户管理模块安装:

修改配置 /usr/local/njet/conf/njet.conf

ini 复制代码
worker_processes auto;

cluster_name njet;
node_name node1;

error_log logs/error.log error;

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;

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")
    }
    server {
        listen       8080;
        error_page 401 =302 /portal;
        client_max_body_size 1000m; 
        location / {
           root html;
        }
        location /icons/ {
            alias /usr/local/njet/apps/__icons/;
            try_files $uri =404;
       }
    }
}
ini 复制代码
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()
           }
        }
    }
}

拷贝 ssh_remote_mod.so

bash 复制代码
sudo cp ssh_remote_mod.so /usr/local/njet/lualib/clib/

重启 njet

arduino 复制代码
sudo systemctl stop njet
sudo systemctl start njet     

将下载后的 portal_1.0.2.npk 文件上传到 njet 主机上,并且主机上安装 curl 及 jq 命令行工具

perl 复制代码
NJET_SITE="http://localhost:8081"

PORTAL_FILE=$(curl -k -s -F "file=@portal_1.0.2.npk"  "$NJET_SITE/api/v1/upload" |jq -r '.file')

TOKEN=$(curl -k -X POST -d '{"login_data":{"username": "agw_admin", "password": "********"}}' -s "$NJET_SITE/api_gateway/auth/login" | jq -r '.token')

curl -X 'POST' \
  "$NJET_SITE/api_gateway/deploy/app" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{"uploaded_file": "$PORTAL_FILE"}"

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

官网 邮件组

相关推荐
xixingzhe219 小时前
Nginx 看懂请求耗时瓶颈
服务器·前端·nginx
北风toto1 天前
Windows 下用 OpenSSL 生成 SSL 密钥并配置 Nginx 教程
windows·nginx·ssl
卜锦元1 天前
Docker Compose 部署 Nginx 1.30.6 完整指南
nginx·docker·容器
小小龙学IT1 天前
Nginx 开源 Web 服务器与反向代理深度解
前端·nginx·开源
Coisinier2 天前
docker命令管理镜像及容器
linux·运维·nginx·docker·容器·操作系统
2301_32241428042 天前
基于web的校园失物招领管理系统59695-计算机毕设 原创(免费领源码+部署教程+开发环境)
mysql·nginx·php·apache·thinkphp·phpstudy·wampserver
flytalei2 天前
从YAML到Nginx服务访问:动手理解 Kubernetes Pod、Deployment 与 Service
运维·nginx·kubernetes
健康活着就好3 天前
# Nginx负载均衡四种策略,从原理到配置
nginx
Vitaliy Kostrov(柯维远)3 天前
谁来承担额外工作?CDN 参与者如何协商资源
nginx·缓存·系统架构·开源·cdn