CoPilot开发指南
CoPilot开发指南
1. CoPilot概述
OpenNJet是一个多进程的程序,有一个Master进程和多个Worker进程,另外还可以创建多个CoPilot进程。CoPilot在Master-Workers进程架构的基础之上进行了扩展,提升了OpenNJet的控制管理和提供服务的能力。比如,可以用CoPilot运行一个Controller,对外提供访问控制;还可以用CoPilot运行一个Broker,作为一个消息中间件。这是两种典型的用法,但并不是全部,受限的是必须遵守CoPilot插件开发规范,而不是CoPilot提供的功能和服务。
Master进程创建了CoPilot进程,并在NJET的整个生命周期过程中管理着CoPilot进程,在根据控制信号停止(-s stop 或 -s quit)OpenNJet时,会停止CoPilot进程;在重新加载配置(-s reload)时,是否停止并创建新的CoPilot进程,是由这个CoPilot进程的so决定,这一点在CoPilot插件规范有描述;在CoPilot进程因为意外挂掉时,会及时创建新的CoPilot进程。
2. CoPilot配置
CoPilot的配置,是在主配置文件中使用helper指令。
指令说明:
Syntax | helper tag so_file conf_file; |
---|---|
Default | — |
Context | main |
参数说明:
参数名称 | 是否必须 | 参数说明 |
---|---|---|
tag | 是 | 指定一个名字标签 |
so_file | 是 | so文件 |
conf_file | 是 | 配置文件 |
下面为示例配置:
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文件,需实现以下接口:
1)unsigned int njt_helper_check_version(void) 注:当前版本号是 1 #define NJT_HELPER_VER 1 2)void njt_helper_run(helper_param param) 注:helper_param是一个struc类型,定义如下
typedef unsigned int (*helper_check_cmd_fp)(void* ctx); typedef struct { size_t conf_fn_len; u_char *conf_fn_data;* *helper_check_cmd_fp check_cmd_fp;* *void* ctx; } helper_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实例,提供了参考。
在OpenNJet执行configure的时候,需要加上参数:–add-dynamic-module=./modules/njet-helper-demo-module
在make编译的时候,编译出 objs/njt_helper_demo_module.so
5.自带的CoPilot实例
CoPilot: broker 实例
broker的功能
broker是一个CoPilot插件,运行在一个单独的CoPilot进程中,该模块提供消息服务端功能, 使用mqtt 协议。
broker的配置使用
broker是在主配置文件中通过helper指令进行配置:
helper broker modules/njt_helper_broker_module.so conf/mqtt.conf;
配置文件必须存在,可以是空文件,未配置的配置项将使用默认配置
mqtt.conf Message Broker 配置文件
配置项 | 必须修改 | 配置说明 |
---|---|---|
log_dest | 否 | 日志输出方法,一般配置为文件输出,配置值为file 文件名(绝对路径)默认: $PREFIX/logs/mosquitto.log |
log_type | 否 | 日志级别: debug, error, warning, notice, information,mqtt库中的日志输出方式和java 中的不一样,配置了某个日志级别,只有该日志级别的消息才会输出到日志中, 因此需要为需要的日志级别单独配置一行。默认: error |
listener | 否 | 监听端口及地址 , 默认: 0 $PREFIX/data/mosquitto.sock |
allow_anonymous | 否 | 是否允许匿名连接,目前配置为true |
persistence | 否 | 是否开启消息持久化 (true, false), 默认: true |
autosave_on_changes | 否 | 是否有消息时进行自动保存 默认: true |
autosave_interval | 否 | 当自动保存开启时,当新消息个数大于这个配置值时,将触发保存操作 默认: 1 |
persistence_location | 否 | 持久化文件保存路径,将在该路径下创建 mosquitto.db , 默认: $PREFIX/data |
CoPilot: njet_ctrl实例
ctrl的功能
ctrl是一个CoPilot插件,运行在一个单独的CoPilot进程中,一方面它继承了所有OpenNJet静态编译的模块,另一方面可以通过load_module指令加载自己的动态模块来扩展功能,提供了强大的控制能力,成为OpenNJet的控制平面。
ctrl的配置使用
ctrl是在主配置文件中通过helper指令进行配置:
helper ctrl modules/njt_helper_ctrl_module.so conf/njet_ctrl.conf;
ctrl的配置文件是上面的helper指令中指定,配置文件中配置的指令分为两类:
1)OpenNJet中标准的指令;
需要注意 :用 error_log 和 access_log 指令指定的log文件要不同于主配置文件中的log文件。
2)通过 load_module 指令加载的动态模块中扩展出来的指令:
ctrl配置文件配的内容示例如下:
load_module modules/njt_http_sendmsg_module.so;
load_module modules/njt_http_location_api_module.so;
load_module modules/njt_ctrl_config_api_module.so;
load_module modules/njt_http_health_check_helper.so;
load_module modules/njt_http_vtsd_module.so;
user njet njet;
error_log logs/error-ctrl.log info;
events {
worker_connections 1024;
}
http {
dyn_sendmsg_conf conf/iot-ctrl.cfg;
access_log logs/access-ctrl.log combined;
server {
listen 8081;
location /api {
dyn_module_api;
}
location /metrics {
vhost_traffic_status_display;
vhost_traffic_status_display_format html;
}
}
}
6.其他问题
SSL的一致性
CoPilot 插件,如果使用了SSL库,需要与Njet 编译时使用的SSL库版本相同。 插件编译时使用的 Include 头文件目录( -I ),及链接时使用的 Library 目录( -L )需要指向相同版本的SSL 库路径。
使用cmake编译时,在CMakeLists.txt文件中的include_directories 及link_directories填入对应SSL库的路径
include_directories(${NJET_SSL_LIB_INCLUDE_DIR})
link_directories(${NJET_SSL_LIB_DIR})