CoPilot 产品体验:提升 OpenNJet 的控制管理和服务提供能力

发布于:2024-05-11 ⋅ 阅读:(23) ⋅ 点赞:(0)

在这里插入图片描述

前言

CoPilot 是 OpenNJet 的一个重要组成部分,它在 Master-Workers 进程架构的基础上进行了扩展,提升了 OpenNJet 的控制管理和提供服务的能力。通过 CoPilot,可以实现诸如运行 Controller、作为消息中间件的 Broker 等多种功能,极大地扩展了 OpenNJet 的应用范围和灵活性。

系统架构介绍

OpenNJet 最早是基于 NGINX1.19 基础,fork 并独立演进的开源应用引擎,并随着 NGINX 版本迭代,吸收上游 NGINX 的更新,已经同步更新到 NGINX1.23.1 版本。OpenNJet 的目标在于适应国内特定的技术规范及标准,如国密算法套件支持,并构建安全可控的云原生数据面,支撑我国云原生产业生态。作为底层引擎,OpenNJet 利用动态加载机制可以实现不同的产品形态,如 API 网关、消息代理、出入向代理,负载均衡,WAF等等。

相比市面其他类型的API网关,高性能是NGINX主要的优点,但动态配置能力的缺乏一直受到业界的诟病。OpenNJet在NGINX的架构上进行了扩充,对其框架进行了改写,增加了 C 及可持久化的动态存储能力,解决了指令配置变更动态生效的关键问题,扩展了OpenNJet的应用场景。

CoPilot 配置

在配置项目之前,首先需要将项目下载到本地。在终端执行如下命令:

git clone git@github.com:OpenNJet/OpenNJet.git

运行如下图:

CoPilot 的配置十分简单,只需在主配置文件中使用 helper 指令即可完成。这种简洁的配置方式使用户能够快速地部署和管理 CoPilot 插件,提高了系统的可维护性和易用性。

helper ctrl modules/njt_helper_ctrl_module.so conf/njet_ctrl.conf;
helper broker modules/njt_helper_broker_module.so conf/mqtt.conf;

以上示例配置了一个 Controller 和一个 Broker,分别运行在不同的 CoPilot 进程中。配置文件的路径可以根据实际情况进行调整,使其符合用户的需求。

CoPilot 插件规范

CoPilot 插件是以动态链接库(so文件)的形式存在的,用户需要按照规范实现一系列接口以确保插件的正确运行。

插件接口

  • njt_helper_check_version(): 检查插件的版本号,确保与CoPilot的兼容性。
  • njt_helper_run(helper_param param): 插件的主函数,负责处理命令和执行相应的操作。
  • njt_helper_ignore_reload(): 指定插件在重新加载配置时是否重启。

体验 CoPilot 实例

CoPilot: Broker 实例

功能介绍

Broker 是一个 CoPilot 插件,提供消息服务端功能,使用 mqtt 协议进行通信。

配置示例

helper broker modules/njt_helper_broker_module.so conf/mqtt.conf;

CoPilot: Ctrl 实例

功能介绍

Ctrl 是一个 CoPilot 插件,提供了强大的控制能力,可以作为 OpenNJet 的控制平面,用于管理和监控系统的运行状态。

配置示例

helper ctrl modules/njt_helper_ctrl_module.so conf/njet_ctrl.conf;

开发其他语言编写的 CoPilot

目标

为了方便其他语言实现的独立功能向 CoPilot 迁移,提供了 Go 语言实现的 CoPilot POC。这个实现可以启动和停止一个简单的 Web 服务器。

主要思路

参考现有的模块,用C语言实现一个新的Helper模块,在初始化阶段调用Go程序启动Web服务器,并等待接收命令进行操作。

具体实现

通过调用Go程序启动Web服务器,并在Helper模块中监控命令,进行相应的操作。以下是一个简化的示例代码:

#include <stdio.h>
#include "njt_helper.h"

unsigned int njt_helper_check_version(void) {
    return NJT_HELPER_VER;
}

void njt_helper_run(helper_param param) {
    // 在事件循环中处理命令
    unsigned int cmd;
    while (1) {
        cmd = param.check_cmd_fp(param.ctx);
        switch (cmd) {
            case NJT_HELPER_CMD_STOP:
                // 执行停止操作
                break;
            case NJT_HELPER_CMD_RESTART:
                // 执行重新启动操作
                break;
            default:
                // 处理其他命令
                break;
        }
    }
}

unsigned int njt_helper_ignore_reload(void) {
    return 1; // 在重新加载配置时不重启
}

这段示例代码是一个简单的 CoPilot 插件,用于启动和停止一个 Web 服务器。让我们逐行解释和扩展这段代码:

  • #include <stdio.h>:包含标准输入输出头文件,用于后续的输出和调试。
  • #include "njt_helper.h":包含CoPilot插件的头文件,其中定义了接口函数和常量。
  • unsigned int njt_helper_check_version(void):这个函数是一个接口函数,用于检查插件的版本号。在实际开发中,可以在这里检查插件的版本号,确保与CoPilot的兼容性。
  • void njt_helper_run(helper_param param):这个函数是插件的主函数,负责处理命令和执行相应的操作。在这里,通过一个无限循环来不断检查命令,并根据不同的命令执行相应的操作。
  • unsigned int njt_helper_ignore_reload(void):这个函数指定插件在重新加载配置时是否重启。在这个示例中,返回值为1,表示在重新加载配置时不重启。

对于这段示例代码的扩展,可以从以下几个方面入手:

  1. 具体操作的实现:在 njt_helper_run 函数中,可以扩展具体的操作实现。比如,在 NJT_HELPER_CMD_STOP 对应的分支中实现停止Web服务器的操作,在 NJT_HELPER_CMD_RESTART 对应的分支中实现重新启动Web服务器的操作。
  2. 命令处理的优化:可以考虑优化命令处理逻辑,使得代码更加健壮和高效。例如,可以引入状态机来管理命令的处理流程,或者使用事件驱动的方式来处理命令。
  3. 错误处理和日志记录:可以添加错误处理和日志记录功能,以便及时发现和解决问题。可以在适当的位置添加错误检查和日志输出语句,帮助定位问题并进行排查。
  4. 参数配置和灵活性:可以考虑添加参数配置功能,使得插件的行为可以根据配置文件进行调整。可以定义一些参数,并提供相应的接口函数来读取和设置这些参数,以实现插件的灵活性和可配置性。
  5. 性能优化和资源管理:可以进行性能优化和资源管理,提高插件的运行效率和资源利用率。可以考虑采用异步IO、线程池等技术来提高性能,或者实现资源的自动回收和释放功能,避免资源泄露和内存溢出问题。

通过对示例代码的解释和扩展,可以更好地理解CoPilot插件的开发和运行原理,从而为实际项目的开发和部署提供参考和指导。

执行 go 程序代码

为了展示如何在 Go 语言中实现 CoPilot 插件,要先启动一个 Web 服务器,用于接收到特定命令时
停止服务器。并在checkCommand函数中模拟了检查命令的操作。然后,在一个无限循环中不断地检查命令,并根据不同的命令执行相应的操作。
执行代码如下:

package main

import (
    "fmt"
    "net/http"
)

// CoPilot插件的主函数,负责处理命令和执行相应的操作
func main() {
    // 在初始化阶段启动Web服务器
    go startServer()

    // 监听命令,并根据不同的命令执行相应的操作
    for {
        // 检查命令
        cmd := checkCommand()
        
        // 根据不同的命令执行相应的操作
        switch cmd {
        case "stop":
            stopServer()
            fmt.Println("Web服务器已停止")
        default:
            fmt.Println("未知命令:", cmd)
        }
    }
}

// 启动Web服务器
func startServer() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, World!")
    })
    fmt.Println("Web服务器已启动")
    http.ListenAndServe(":8080", nil)
}

// 停止Web服务器
func stopServer() {
    // 实现停止Web服务器的操作
    // 这里省略具体实现,可以根据实际需求来编写
}

// 检查命令
func checkCommand() string {
    // 实现检查命令的操作
    // 这里省略具体实现,可以根据实际需求来编写
    return "stop" // 这里只是一个示例,实际可以根据情况返回不同的命令
}

在这个示例中,我们只实现了停止 Web 服务器的操作,实际中还可以根据需要扩展其他操作。

功能扩展

CoPilot 的功能扩展并不仅限于运行 Controller 和 Broker,这只是两种典型的用法。只要遵守了 CoPilot 插件开发规范,用户可以根据自己的需求开发各种自定义的功能,并且在 OpenNJet 的基础上运行,从而实现更多样化的服务。

Master 进程负责创建和管理 CoPilot 进程,保证其正常运行。在 OpenNJet 的生命周期中,Master 进程会监控 CoPilot 进程的状态,并在需要时启动、停止或重新加载。这种自动化的进程管理保证了 OpenNJet 系统的稳定性和可靠性。

总结

本文对 CoPilot 作为 OpenNJet 重要组成部分的详细介绍,让读者了解了其架构、功能、配置方法以及开发实例。希望通过阅读文章,读者能对 CoPilot 有更深入的了解,并且对其在 OpenNJet 中的作用和优势有了清晰的认识。我相信,CoPilot 的引入将极大地提升 OpenNJet 的控制管理和服务提供能力,为用户提供更加灵活和强大的解决方案。


网站公告

今日签到

点亮在社区的每一天
去签到