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})