CoPilot 开发指南

飞不高  论坛元老 | 2024-10-14 02:13:27 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1663|帖子 1663|积分 4989

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
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 进程。
CoPilot 配置

CoPilot的配置,是在主配置文件中使用helper指令。
指令阐明:

参数阐明:

示例配置
  1. helper ctrl modules/njt_helper_ctrl_module.so conf/njet_ctrl.conf;
  2. helper broker modules/njt_helper_broker_module.so conf/mqtt.conf;
  3. helper ha modules/njt_helper_ha_module.so conf/vrrp.conf;
复制代码
CoPilot 插件规范

CoPilot插件的情势是一个so文件,需实现以下接口:
  1. 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类型,定义如下
  2. ​      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;
  3. ​      在njt_helper_run的事件循环中,需调用param.check_cmd_fp()接收命令
  4. ​      例如:      unsigned int cmd;      cmd = param.check_cmd_fp(param.ctx);
  5. ​      命令宏定义如下:      #define NJT_HELPER_CMD_NO          0      #define NJT_HELPER_CMD_STOP       1      #define *NJT_HELPER_CMD_RESTART*  2
  6. ​      
  7. ​      接收到命令后,需进行命令处理。      NJT_HELPER_CMD_STOP命令,要进行停止操作;      NJT_HELPER_CMD_RESTART 为预留命令,暂不会发送该命令,在事件处理中可以按停止操作处理该命令,或者执行自身业务逻辑的重新开始。
  8. 3)unsigned int njt_helper_ignore_reload(void)
  9. 返回1,表示该so的copilot进程,不会在reload的时候重启。
  10. 放回0,表示该so的copilot进程,会在reload的时候重启。
  11. 注1:so可以不实现该接口。若不实现,则等同于返回0。
  12. 注2:如果so实现该接口并且返回1,那么在reload的时候该so的copilot进程不会重启,但是有一点需要注意:reload的时候配置文件中需保留原helper指令,这是配置上的强制要求,不满足此要求会导致reload失败。
复制代码
开发实例

开发一个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
自带的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 配置文件


CoPilot: njet_ctrl实例

ctrl的功能

ctrl是一个CoPilot插件,运行在一个单独的CoPilot进程中,一方面它继续了所有OpenNJet静态编译的模块,另一方面可以通过load_module指令加载自己的动态模块来扩展功能,提供了强盛的控制能力,成为OpenNJet的控制平面。
ctrl的配置使用

ctrl是在主配置文件中通过helper指令进行配置:
  1. 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配置文件配的内容示比方下:
  1. load_module modules/njt_http_sendmsg_module.so;
  2. load_module modules/njt_http_location_api_module.so;
  3. load_module modules/njt_ctrl_config_api_module.so;
  4. load_module modules/njt_http_health_check_helper.so;
  5. load_module modules/njt_http_vtsd_module.so;
  6. user njet njet;
  7. error_log logs/error-ctrl.log info;
  8. events {
  9.     worker_connections  1024;
  10. }
  11. http {
  12.     dyn_sendmsg_conf conf/iot-ctrl.cfg;
  13.     access_log logs/access-ctrl.log combined;
  14.     server {
  15.         listen       8081;
  16.         location /kv  {
  17.             dyn_sendmsg_kv;
  18.         }
  19.         location /config {
  20.             config_api;
  21.         }
  22.         location /dyn_loc {
  23.             dyn_location_api;
  24.         }
  25.         location /hc {
  26.                 health_check_api;
  27.         }
  28.         location /metrics {
  29.             vhost_traffic_status_display;
  30.             vhost_traffic_status_display_format html;
  31.         }
  32.     }
  33. }
复制代码
调用其他语言编写的CoPilot

go-copilot开发

目标

在OpenNJet架构中,sidecar agent/KIC agent都将迁移为coPilot,目前他们都实现为独立的go 程序,需要利用cgo的互操作性,提供一个go实现的coPilot POC,以方便其他go实现的独建功能向coPilot迁移。
主要思路

参照现有的njt_ctrl和njt_broker模块,用C语言实现一个简朴的新helper模块,里面在初始化阶段调用go-start()函数启动go实现的服务,同时等候接收到命令,并进行命令处置惩罚。 NJT_HELPER_CMD_STOP命令,要进行制止操作,调用go-stop(); NJT_HELPER_CMD_RESTART 为预留命令,暂不会发送该命令,在事件处置惩罚中可以按制止操作处置惩罚该命令,或者实行自身业务逻辑的重新开始,这个命令先留着一个接口go-restart(),详细实现以后再考虑。
之后是在go语言实现,目前先实现启动制止一个webserver,以后再根据需要实现其他功能。
详细实现(暂时只是启动/制止一个go的webserver)

目前这个模块的功能主要是启动/制止go程序,以是比njt_ctrl和njt_broker模块的实现要简朴一些。
目前将helper中指定的conf路径作为参数传入go程序,作为config文件的位置,以后可以在里面参加要加载的模块;(模块名,启动参数,配置文件位置等)。
最初尝试在c进程中通过导入*.so文件,然后调用相应的导出函数的方式启动web server,但是各种尝试都不乐成。
最终方案是参考nginx-unit和njt_execute实现,通过二进制文件路径来调用,焦点代码为
  1. njt_pid_t njt_helper_go_start(njt_cycle_t *cycle, char *prefix, char *fullfn) {
  2.     njt_exec_ctx_t ctx;
  3.     char *n, *p;
  4.     char *name = "gocop";
  5.     njt_pid_t pid;
  6.     //这里是拼接出go二进制文件的路径,install脚本会在conf-prefix路径下作了一个软链接
  7.     n = njt_calloc(njt_strlen(prefix) + njt_strlen(name) + 1, cycle->log);
  8.     p = (char *)njt_cpymem(n, prefix, njt_strlen(prefix));
  9.     njt_cpystrn((u_char *)p, (u_char *)name, strlen(name) + 1);
  10.    
  11.     ctx.path = n;
  12.     ctx.name = "go copilot in njt_execute";
  13.     ctx.argv = (char* const[]){name, "--conf", fullfn, NULL}; //命令行参数,指定了配置文件位置
  14.     ctx.envp = (char* const[]){"GIN_MODE=release",NULL}; //要传入的环境变量
  15.     pid = njt_execute(cycle, &ctx);
  16.     njt_free(n);
  17.     return pid;
  18. }
复制代码
模块中会保存新天生的进程的pid,供stop命令使用,kill(pid, SIGTERM);
编译OpenNJet module

需要修改 auto/options
  1. # 在 OPENSSL=NONE 下面增加
  2. USE_GOCOP=NO
  3. GOCOP_PATH=NONE
  4. # 在--with-openssl-opt=*)            OPENSSL_OPT="$value"       ;; 之前增加
  5. --with-gocop=*)                      GOCOP_PATH="$value"           ;;
  6. # 在--with-openssl=DIR                 set path to OpenSSL library sources下面增加
  7. --with-gocop=PATH                  set path to gocop binrary executable
复制代码
修改auto/install,增长脚本,在指定了go文件路径后,把该文件复制到njet的相同目录下,并在配置文件目录下做了一个软链接。假如文件不存在,就什么也不做。
  1. if test -n "$GOCOP_PATH"; then
  2. if test -f "$GOCOP_PATH"; then
  3.     cat << END                                                >> $NJT_MAKEFILE
  4.         cp $GOCOP_PATH '\$(DESTDIR)`dirname "$NJT_SBIN_PATH"`/gocop'
  5.         ln -sf '\$(DESTDIR)`dirname "$NJT_SBIN_PATH"`/gocop' '\$(DESTDIR)$NJT_CONF_PREFIX/gocop'
  6. END
  7. fi
  8. fi
复制代码
修改build_cc.sh
  1. #增加
  2. NJET_MODULES="$NJET_MODULES --add-dynamic-module=./modules/njet-helper-go-module"
  3. #在LIB_SRC_PATH上增加
  4. LIB_SRC_PATH=" --with-openssl=auto/lib/tassl --with-pcre=auto/lib/pcre-8.45 --with-gocop=/root/go/src/gitee.com/liismn/go-copilot/cmd/main"
复制代码
其他题目

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

飞不高

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表