<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>开发 :: NJET文档</title>
    <link>https://docs.njet.org.cn/docs/v4.0.1/development/index.html</link>
    <description>本章节主要面向开发者，包含OpenNJet开发的编码规范，第三方模块迁移指南，CoPilot开发等内容。</description>
    <generator>Hugo</generator>
    <language>zh</language>
    <lastBuildDate>Tue, 26 Aug 2025 15:48:51 +0800</lastBuildDate>
    <atom:link href="https://docs.njet.org.cn/docs/v4.0.1/development/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>OpenNJet 编码规范</title>
      <link>https://docs.njet.org.cn/docs/v4.0.1/development/coding_conventions/index.html</link>
      <pubDate>Tue, 26 Aug 2025 10:00:12 +0800</pubDate>
      <guid>https://docs.njet.org.cn/docs/v4.0.1/development/coding_conventions/index.html</guid>
      <description>OpenNJet 编码规范以及新手指引 1.简介 本文主要介绍OpenNJet项目编码规范以及新手指引，主要是帮助开发者规范自己的代码格式以及保持风格一致，并帮助新手开发者更快的上手。&#xA;2.基础指引 2.1代码布局 . ├── 3rd_lib 依赖的第三方动态库, 比如libmosquitto_emb.so ├── build/rpm rpm包编译脚本 ├── auto 自动检测系统环境以及编译相关的脚本 │ ├── cc 关于编译器相关的编译选项的检测脚本 │ ├── lib OpenNJet编译所需要的一些库的检测脚本 │ ├── os 与平台相关的一些系统参数与系统调用相关的检测 │ └── types 与数据类型相关的一些辅助脚本 ├── conf 存放默认配置文件，在make install后，会拷贝到安装目录中去 ├── contrib 存放一些实用工具，如geo配置生成工具（geo2njet.pl） ├── html 存放默认的网页文件，在make install后，会拷贝到安装目录中去 ├── repos 存放yum数据源 ├── doc OpenNJet的api文档 │ ├── swagger openapi 接口网页文档 │ ├── gui 前端展示页面文档 │ └── manual OpenNJet文档手册 ├── luajit luajit ├── lualib lualib ├── modules OpenNJet动态模块以及util模块 ├── openapi openapi 定义文件 └── src 存放OpenNJet的源代码 ├── core OpenNJet的核心源代码，包括常用数据结构的定义，以及OpenNJet初始化运行的核心代码如main函数 ├── event 对系统事件处理机制的封装，以及定时器的实现相关代码 │ └── modules 不同事件处理方式的模块化，如select、poll、epoll、kqueue等 ├── http OpenNJet作为http服务器相关的代码 │ └── modules 包含http的各种功能模块 ├── ext/lua lua模块 ├── mail OpenNJet作为邮件代理服务器相关的代码 ├── stream tcp/udp四层网络代理服务器相关的代码 ├── misc 一些辅助代码，测试c++头的兼容性，以及对google_perftools的支持 └── os 主要是对各种不同体系统结构所提供的系统函数的封装，对外提供统一的系统调用接口 2.2include文件 以下两个语句必须出现在 每个OpenNJet文件的开头：</description>
    </item>
    <item>
      <title>第三方模块迁移指南</title>
      <link>https://docs.njet.org.cn/docs/v4.0.1/development/third_party_module/index.html</link>
      <pubDate>Tue, 26 Aug 2025 10:06:51 +0800</pubDate>
      <guid>https://docs.njet.org.cn/docs/v4.0.1/development/third_party_module/index.html</guid>
      <description>本文以安装 headers-more-nginx-module-0.37 举例，其他情况类似：&#xA;一. 下载第三方包，如：headers-more-nginx-module-0.37.zip 二. 解压缩 unzip headers-more-nginx-module-0.37.zip 三. 解压后，文件夹名字 headers-more-nginx-module-0.37 四. 拷贝到 njet modules 目录下 cp -fr headers-more-nginx-module-0.37 modules/ 五. 进入模块目录 cd modules/headers-more-nginx-module-0.37 六.源代码，修改函数，变量。执行： 1. grep NGINX_ -rl ./* | xargs sed -i &#39;s/NGINX/NJET/g&#39; 2. grep nginx -rl ./* | xargs sed -i &#39;s/nginx/njet/g&#39; 3. grep NGX_ -rl ./* | xargs sed -i &#39;s/NGX_/NJT_/g&#39; 4. grep ngx_ -rl ./* | xargs sed -i &#39;s/ngx_/njt_/g&#39; 5. grep Nginx -rl ./* | xargs sed -i &#39;s/Nginx/NJet/g&#39; 6. grep ngx -rl ./* | xargs sed -i &#39;s/ngx/njt/g&#39; 七. 进入模块源码目录,源文件改名字 cd src/ for i in ls; do mv -f $i `echo $i | sed &#39;s/^ngx_/njt_/&#39;`; done 八. 返回到njet 目录。 九. 配置编译类型。动态或静态 静态编译。添加模块路径到 modules_static echo &#34;./modules/headers-more-nginx-module-0.37&#34; &gt;&gt; modules_static 动态编译。 添加模块路径到 modules_dynamic echo &#34;./modules/headers-more-nginx-module-0.37&#34; &gt;&gt; modules_dynamic 动态编译的，使用时需要动态加载。 修改 njet.conf 文件</description>
    </item>
    <item>
      <title>CoPilot开发指南</title>
      <link>https://docs.njet.org.cn/docs/v4.0.1/development/copilot/index.html</link>
      <pubDate>Tue, 26 Aug 2025 10:44:46 +0800</pubDate>
      <guid>https://docs.njet.org.cn/docs/v4.0.1/development/copilot/index.html</guid>
      <description>CoPilot开发指南 1. CoPilot概述 OpenNJet是一个多进程的程序，有一个Master进程和多个Worker进程，另外还可以创建多个CoPilot进程。CoPilot在Master-Workers进程架构的基础之上进行了扩展，提升了OpenNJet的控制管理和提供服务的能力。比如，可以用CoPilot运行一个Controller，对外提供访问控制；还可以用CoPilot运行一个Broker，作为一个消息中间件。这是两种典型的用法，但并不是全部，受限的是必须遵守CoPilot插件开发规范，而不是CoPilot提供的功能和服务。&#xA;Master进程创建了CoPilot进程，并在NJET的整个生命周期过程中管理着CoPilot进程，在根据控制信号停止（-s stop 或 -s quit）OpenNJet时，会停止CoPilot进程；在重新加载配置（-s reload）时，是否停止并创建新的CoPilot进程，是由这个CoPilot进程的so决定，这一点在CoPilot插件规范有描述；在CoPilot进程因为意外挂掉时，会及时创建新的CoPilot进程。&#xA;2. CoPilot配置 CoPilot的配置，是在主配置文件中使用helper指令。&#xA;指令说明：&#xA;Syntax helper tag so_file conf_file; Default — Context main 参数说明：&#xA;参数名称 是否必须 参数说明 tag 是 指定一个名字标签 so_file 是 so文件 conf_file 是 配置文件 下面为示例配置：&#xA;helper ctrl modules/njt_helper_ctrl_module.so conf/njet_ctrl.conf; helper broker modules/njt_helper_broker_module.so conf/mqtt.conf; helper ha modules/njt_helper_ha_module.so conf/vrrp.conf; 3.CoPilot插件规范 CoPilot插件的形式是一个so文件，需实现以下接口：&#xA;1）unsigned int njt_helper_check_version(void) 注：当前版本号是 1 #define NJT_HELPER_VER 1 2）void njt_helper_run(helper_param param) 注：helper_param是一个struct类型，定义如下 typedef struct { njt_str_t conf_fn; njt_str_t conf_fullfn; helper_check_cmd_fp check_cmd_fp; void *ctx; void *cycle;//njt_cycle_t *cycle; } helper_param; typedef void (*njt_helper_run_fp)(helper_param param); 在njt_helper_run的事件循环中，需调用param.check_cmd_fp()接收命令 例如： unsigned int cmd; cmd = param.check_cmd_fp(param.ctx); 命令宏定义如下： #define NJT_HELPER_CMD_NO 0 #define NJT_HELPER_CMD_STOP 1 #define NJT_HELPER_CMD_RESTART 2 接收到命令后，需进行命令处理。 NJT_HELPER_CMD_STOP命令，要进行停止操作； NJT_HELPER_CMD_RESTART 为预留命令，暂不会发送该命令，在事件处理中可以按停止操作处理该命令，或者执行自身业务逻辑的重新开始。 3）unsigned int njt_helper_ignore_reload(void) 返回1，表示该so的copilot进程，不会在reload的时候重启。 放回0，表示该so的copilot进程，会在reload的时候重启。 注1：so可以不实现该接口。若不实现，则等同于返回0。 注2：如果so实现该接口并且返回1，那么在reload的时候该so的copilot进程不会重启，但是有一点需要注意：reload的时候配置文件中需保留原helper指令，这是配置上的强制要求，不满足此要求会导致reload失败。 4.开发实例 开发一个demo的CoPilot插件，与开发一个module相比，有一些相似的地方，比如config文件的编写，也存在不同的地方，比如CoPilot插件不需要提像module那样实现njt_module_t中的commands和ctx等，而是需要按照CoPilot插件规范进行实现。下面的CoPilot实例，提供了参考。</description>
    </item>
    <item>
      <title>Event 框架介绍及开发</title>
      <link>https://docs.njet.org.cn/docs/v4.0.1/development/event_framework/index.html</link>
      <pubDate>Tue, 26 Aug 2025 15:48:51 +0800</pubDate>
      <guid>https://docs.njet.org.cn/docs/v4.0.1/development/event_framework/index.html</guid>
      <description>OpenNJet Event 框架介绍 OpenNJet 实现了Copilot: Ctrl, 在Ctrl 中加载不同的动态模块，负责对外提供HTTP API 接口， 各个API模块中会调用 SendMsg 模块提供的函数进行消息的发送，及设置回调函数（RR消息）。 SendMsg 模块是MQTT协议的客户端，连接到服务端（Copilot: broker)。动态配置相关的数据将发送到 /worker_a/# 主题。&#xA;OpenNJet 中提供的KV模块（静态编译）对外提供了注册函数， 业务模块在模块初始化时，设置对应主题的回调函数，当KV 模块收到相应主题的消息后，将触发回调。KV模块是MQTT协议的客户端，将连接到Copilot: broker 并订阅一些主题。&#xA;Privilege Agent 进程中的KV模块订阅了 /worker_a/# 主题， 因此Ctrl 发出的配置数据 /worker_a/{ins, dyn}/{module}，Privilege Agent 进程的KV 模块收到消息后，将查询回调函数列表，如果对应的模块有配置回调，就触发业务模块的调用，获取业务模块返回后，将直接使用 rpc_get_handler 获取业务模块的全量配置数据，然后将消息广播到 /dyn/{module} 主题。由于Privilege Agent是消息发送方，不会收到本次发送的消息，而其它所有 worker 进程将收到该消息，并触发业务模块的回调，从而将全量配置同步到所有worker中。&#xA;MQTT 协议及工具安装 MQTT介绍 MQTT（Message Queuing Telemetry Transport）是一种轻量级、基于发布-订阅模式的消息传输协议。&#xA;几个关于MQTT的重要概念：&#xA;RETAIN 消息 当我们使用MQTT客户端发布消息（ PUBLISH ）时，如果将RETAIN标志位设置为 true ，那么MQTT服务器会将最近收到的一条RETAIN标志位为 true 的消息保存在服务器端（内存或文件）。 特别注意：MQTT服务器只会为每一个Topic保存最近收到的一条RETAIN标志位为true的消息！</description>
    </item>
    <item>
      <title>NJET模块嵌入lua指南</title>
      <link>https://docs.njet.org.cn/docs/v4.0.1/development/njet_lua/index.html</link>
      <pubDate>Tue, 26 Aug 2025 15:42:32 +0800</pubDate>
      <guid>https://docs.njet.org.cn/docs/v4.0.1/development/njet_lua/index.html</guid>
      <description>介绍 在NJET和其它系统集成时，有时需要对接外部系统，因为面临的外部系统千差万别， 为每个系统开发单独的c模块实现繁琐，因此可以通过嵌入lua的模式实现定制。作为server端， openresty 开源的lua模块可以满足需要,但作为client，需要额外的框架及lua库&#xA;client嵌入架构 额外Lua库 第三方的Lua 库 在auto/lib/luapkg 目录下&#xA;由于rpm 构建时，编译时会使用源码目录中的luajit, 以及rpm临时安装文件会拷贝到 rpmbuild 的 %{buildroot}目录，因此所有放到 luapkg 目录下的第三方模块，需要稍微做一些修改，Makefile 中的编译及安装阶段需要识别以下环境变量：&#xA;变量 描述 DESTDIR make 时指定的安装路径前缀 LUA_MODULE_DIR Lua 模块安装路径 LUA_CMODULE_DIR Lua C 模块安装路径 LUA_INCLUDE_DIR Lua 头文件地址 LUA_LIB_DIR Lua 链接的库地址 这些环境变量外部构建的脚本可能会设置不同的值, 如果外部环境变量有设置这些值，第三方模块的编译及安装脚本需要使用外部设置的值。例如：&#xA;LUA_MODULE_DIR ?= /usr/local/share/lua/5.1 LUA_CMODULE_DIR ?= /usr/local/lib/lua/5.1 LUA_INCLUDE_DIR ?= /usr/local/include/luajit-2.1 LUA_LIB_DIR ?= /usr/local/lib 。。。。 install: mkdir -p $(DESTDIR)$(LUA_CMODULE_DIR)/smithsnmp cp core/core.so $(DESTDIR)$(LUA_CMODULE_DIR)/smithsnmp/ cp -a lualib/* $(DESTDIR)$(LUA_MODULE_DIR)</description>
    </item>
  </channel>
</rss>