# LinkAgg 模块 ## 概述 **⚠️ Beta 版本** LinkAgg(Link Aggregation)模块提供同端口链路聚合功能,支持单端口监听并将请求转发到多个后端服务器。 --- ## 版本状态 | 状态 | 说明 | |------|------| | **版本** | v2.2.1-beta | | **稳定性** | Beta - 功能完整,但可能存在未发现的问题 | | **建议** | 生产环境使用前请充分测试 | --- ## 功能限制 ### 后端数量限制 | 限制项 | 值 | 说明 | |--------|-----|------| | 最大后端数量 | **512** | 索引范围:0-511 | | 后端索引 | 0 ~ 511 | 从 0 开始,依次递增 | ```c // 后端数量限制为 512 个 // 索引范围: 0 到 511 nl_linkagg_add_http_backend(la, "127.0.0.1", 8081, 1); // 后端 0 nl_linkagg_add_http_backend(la, "127.0.0.1", 8082, 1); // 后端 1 // ... 最多添加 512 个后端 // 超过 512 个后,返回错误 int result = nl_linkagg_add_http_backend(la, "127.0.0.1", 8083, 1); // result = -8 (超过最大后端数量) ``` ### 同端口 ID 命名 LinkAgg 支持通过 **ID** 标识不同的服务端口。 #### 命名格式 ID 必须符合 `xxx.xxx` 格式(点分隔字符串): | 格式 | 示例 | 说明 | |------|------|------| | `xxx.xxx` | `api.users`、`web.backend`、`db.primary` | 必须包含一个点号 | ```c // 正确的 ID 格式 nl_linkagg_set_port_id(la, "api.users"); // ✅ nl_linkagg_set_port_id(la, "web.backend"); // ✅ nl_linkagg_set_port_id(la, "db.primary"); // ✅ // 错误的 ID 格式(编译/运行时错误) nl_linkagg_set_port_id(la, "apiusers"); // ❌ 缺少点号 nl_linkagg_set_port_id(la, "api..users"); // ❌ 点号位置错误 nl_linkagg_set_port_id(la, ".api.users"); // ❌ 不能以点号开头 nl_linkagg_set_port_id(la, "api.users."); // ❌ 不能以点号结尾 ``` #### ID 冲突检测 **同一进程内,同一端口的 ID 必须唯一** ```c nl_linkagg_t* la = nl_linkagg_create(8080); // 设置第一个端口的 ID nl_linkagg_set_port_id(la, "api.users"); // ✅ 成功 // 设置第二个端口的 ID // 如果使用相同 ID,会被拒绝: int result = nl_linkagg_set_port_id(la, "api.users"); // result = -9 (不接入,ID被占用) ``` ### 限制错误码 | 错误码 | 含义 | |--------|------| | `-8` | 超过最大后端数量(512个) | | `-9` | 不接入,ID被占用 | | `-10` | ID 格式错误(不符合 xxx.xxx 格式) | --- ## 平台支持 | 平台 | 状态 | 说明 | |------|------|------| | Windows | ✅ 完全支持 | 需要 IPC 模块支持 | | Linux | ✅ 完全支持 | 需要 IPC 模块支持 | | macOS | ❌ 不支持 | 依赖的 IPC 模块不支持 macOS | --- ## 模块依赖 LinkAgg 模块**强依赖**以下模块: | 模块 | 依赖类型 | 说明 | |------|----------|------| | **netleaf** | **必需** | 主库,提供基础网络功能 | | **netleaf_ipc** | **必需** | IPC通讯模块,用于IPC后端支持 | ### 依赖关系说明 1. **netleaf (主库)** - 提供 HTTP 服务器和 TCP socket 功能 - LinkAgg 的基础网络层依赖 2. **netleaf_ipc (IPC模块)** - **必需依赖**,即使不使用 IPC 后端 - 提供进程间通讯能力 - 由于 IPC 模块不支持 macOS,LinkAgg 也**不支持 macOS** ### 依赖检查 ```c #include "netleaf_linkagg.h" int main() { // 检查 LinkAgg 是否可用 if (!nl_linkagg_is_available()) { printf("LinkAgg is not available on this platform\n"); printf("Reasons: IPC module not available (macOS not supported)\n"); return 1; } // 检查 IPC 模块状态 if (!nl_ipc_is_available()) { printf("IPC module is not available - LinkAgg requires IPC\n"); return 1; } // 继续使用 LinkAgg... return 0; } ``` --- ## 负载均衡策略 | 策略 | 描述 | 适用场景 | |------|------|----------| | Round Robin | 轮询,依次分配请求 | 后端性能相近时 | | Random | 随机选择后端 | 简单场景 | | Least Connections | 选择连接数最少的后端 | 后端负载差异较大时 | | Weighted Round Robin | 加权轮询,根据权重分配 | 需要按性能分配时 | --- ## API 参考 ### 平台检测 ```c // 检查LinkAgg模块是否可用 int nl_linkagg_is_available(void); // 初始化LinkAgg模块(会自动初始化依赖模块) int nl_linkagg_init(void); // 关闭LinkAgg模块 void nl_linkagg_shutdown(void); ``` ### 创建和配置 ```c // 创建链路聚合实例 // port: 监听端口 nl_linkagg_t* nl_linkagg_create(int port); // 设置负载均衡策略 void nl_linkagg_set_strategy(nl_linkagg_t* la, nl_linkagg_strategy_t strategy); // 添加HTTP后端 // host: 后端主机地址 // port: 后端端口 // weight: 权重(用于Weighted Round Robin策略) int nl_linkagg_add_http_backend(nl_linkagg_t* la, const char* host, int port, int weight); // 添加IPC后端 // path: IPC路径(Windows: \\.\pipe\, Linux: /path/to/socket) // weight: 权重 int nl_linkagg_add_ipc_backend(nl_linkagg_t* la, const char* path, int weight); // 启动链路聚合服务 int nl_linkagg_start(nl_linkagg_t* la); // 停止链路聚合服务 void nl_linkagg_stop(nl_linkagg_t* la); // 销毁链路聚合实例 void nl_linkagg_destroy(nl_linkagg_t* la); ``` ### 状态查询 ```c // 获取后端数量 int nl_linkagg_get_backend_count(nl_linkagg_t* la); // 获取当前策略 nl_linkagg_strategy_t nl_linkagg_get_strategy(nl_linkagg_t* la); // 获取后端状态 // index: 后端索引(从0开始) // 返回值: 0=正常, -1=不可用 int nl_linkagg_get_backend_status(nl_linkagg_t* la, int index); // 获取当前连接数 int nl_linkagg_get_connection_count(nl_linkagg_t* la); ``` ### 统计信息 ```c // 获取总请求数 uint64_t nl_linkagg_get_total_requests(nl_linkagg_t* la); // 获取各后端请求数 int nl_linkagg_get_backend_requests(nl_linkagg_t* la, int index, uint64_t* count); ``` --- ## 使用示例 ### 示例 1:基本用法(HTTP后端) ```c #include "netleaf_linkagg.h" #include int main() { // === 平台检测 === if (!nl_linkagg_is_available()) { printf("LinkAgg is not available (requires IPC module)\n"); return 1; } // === 初始化模块 === if (nl_linkagg_init() != 0) { printf("Failed to initialize LinkAgg\n"); return 1; } // === 创建链路聚合实例 === nl_linkagg_t* la = nl_linkagg_create(8080); if (!la) { printf("Failed to create LinkAgg instance\n"); nl_linkagg_shutdown(); return 1; } // === 配置负载均衡策略 === nl_linkagg_set_strategy(la, NL_LINKAGG_STRATEGY_ROUND_ROBIN); // === 添加HTTP后端 === nl_linkagg_add_http_backend(la, "127.0.0.1", 8081, 1); // 权重1 nl_linkagg_add_http_backend(la, "127.0.0.1", 8082, 2); // 权重2 nl_linkagg_add_http_backend(la, "127.0.0.1", 8083, 1); // 权重1 // === 启动服务 === if (nl_linkagg_start(la) != 0) { printf("Failed to start LinkAgg\n"); nl_linkagg_destroy(la); nl_linkagg_shutdown(); return 1; } printf("LinkAgg service started on port 8080\n"); printf("Backends: 3 HTTP servers\n"); // === 保持运行 === while (1) { #ifdef _WIN32 Sleep(1000); #else sleep(1); #endif } // === 清理 === nl_linkagg_stop(la); nl_linkagg_destroy(la); nl_linkagg_shutdown(); return 0; } ``` ### 示例 2:混合后端(HTTP + IPC) ```c #include "netleaf_linkagg.h" #include int main() { // 初始化 if (!nl_linkagg_is_available()) { printf("LinkAgg not available\n"); return 1; } nl_linkagg_init(); // 创建实例 nl_linkagg_t* la = nl_linkagg_create(8080); // 设置策略 nl_linkagg_set_strategy(la, NL_LINKAGG_STRATEGY_LEAST_CONNECTIONS); // 添加HTTP后端 nl_linkagg_add_http_backend(la, "127.0.0.1", 8081, 1); nl_linkagg_add_http_backend(la, "127.0.0.1", 8082, 1); // 添加IPC后端 #ifdef _WIN32 nl_linkagg_add_ipc_backend(la, "\\\\.\\pipe\\backend_service", 1); #else nl_linkagg_add_ipc_backend(la, "/tmp/backend_service", 1); #endif // 启动 nl_linkagg_start(la); printf("LinkAgg started with 2 HTTP + 1 IPC backends\n"); while (1) { #ifdef _WIN32 Sleep(1000); #else sleep(1); #endif } // 清理 nl_linkagg_stop(la); nl_linkagg_destroy(la); nl_linkagg_shutdown(); return 0; } ``` ### 示例 3:选择不同的负载均衡策略 ```c // 轮询(默认) nl_linkagg_set_strategy(la, NL_LINKAGG_STRATEGY_ROUND_ROBIN); // 随机 nl_linkagg_set_strategy(la, NL_LINKAGG_STRATEGY_RANDOM); // 最小连接数 nl_linkagg_set_strategy(la, NL_LINKAGG_STRATEGY_LEAST_CONNECTIONS); // 加权轮询 nl_linkagg_set_strategy(la, NL_LINKAGG_STRATEGY_WEIGHTED_ROUND_ROBIN); ``` --- ## 功能特性 | 特性 | 说明 | 状态 | |------|------|------| | 单端口监听 | 所有请求通过一个端口进入 | ✅ | | 多后端支持 | 支持HTTP和IPC两种后端类型 | ✅ | | 负载均衡 | 四种负载均衡策略可选 | ✅ | | 加权分配 | 支持后端权重配置 | ✅ | | 健康检查 | 自动检测后端健康状态 | ⚠️ Beta | | 故障转移 | 自动跳过不可用的后端 | ⚠️ Beta | | 统计信息 | 请求计数和分发统计 | ✅ | --- ## 架构说明 ```mermaid flowchart TD C["客户端请求"] --> L["LinkAgg 监听端口 (8080)"] L --> LB["负载均衡器
(Round Robin / Random / LeastConn / Weighted)"] LB --> B1["HTTP 后端 :8081"] LB --> B2["HTTP 后端 :8082"] LB --> B3["IPC 后端 /tmp/..."] ``` --- ## 线程安全 LinkAgg模块采用线程安全设计: | 特性 | 说明 | |------|------| | 互斥锁保护 | 内部使用互斥锁保护共享资源 | | 并发请求 | 支持高并发请求处理 | | 线程安全API | 所有公开API均可从多个线程调用 | --- ## 错误码 | 错误码 | 含义 | |--------|------| | `0` | 成功 | | `-1` | 通用错误 | | `-2` | 平台不支持(依赖IPC不可用) | | `-3` | 内存分配失败 | | `-4` | 无效参数 | | `-5` | 端口绑定失败 | | `-6` | 后端添加失败 | | `-7` | 服务未启动 | | `-8` | 超过最大后端数量(512个) | | `-9` | 不接入,ID被占用 | | `-10` | ID 格式错误(不符合 xxx.xxx 格式) | --- ## 模块信息 ```c NL_MODULE_INFO_BEGIN(linkagg, NL_MODULE_TYPE_LINKAGG) NL_MODULE_NAME("LinkAgg") NL_MODULE_VERSION("2.2.1-beta") NL_MODULE_DESCRIPTION("Same-port link aggregation and load balancing (Beta)") NL_MODULE_AUTHOR("508364") NL_MODULE_PLATFORM(WINDOWS, LINUX) NL_MODULE_DEPENDENCY(netleaf) NL_MODULE_DEPENDENCY(netleaf_ipc) NL_MODULE_INFO_END() ``` --- ## 最佳实践 ### 1. 始终检查可用性 ```c if (!nl_linkagg_is_available()) { // LinkAgg不可用,提供替代方案 printf("LinkAgg requires IPC module, falling back to direct HTTP\n"); } ``` ### 2. 合理配置后端权重 ```c // 根据后端性能设置权重 nl_linkagg_add_http_backend(la, "127.0.0.1", 8081, 2); // 高性能服务器 nl_linkagg_add_http_backend(la, "127.0.0.1", 8082, 1); // 普通服务器 ``` ### 3. 监控后端状态 ```c // 定期检查后端状态 for (int i = 0; i < nl_linkagg_get_backend_count(la); i++) { int status = nl_linkagg_get_backend_status(la, i); if (status != 0) { printf("Backend %d is unavailable\n", i); } } ``` ### 4. 使用前启动依赖服务 ```c // 如果使用IPC后端,确保IPC服务已启动 // 否则请求会失败或超时 ``` --- ## 常见问题 ### Q: LinkAgg 为什么不支持 macOS? **A:** LinkAgg **强依赖** IPC 模块,而 IPC 模块不支持 macOS。如需跨平台解决方案,建议使用纯 HTTP 后端。 ### Q: 可以只使用 HTTP 后端而不使用 IPC 吗? **A:** 可以,但 IPC 模块仍然会被加载(作为必需依赖)。如果只是需要 HTTP 负载均衡,也可以考虑其他方案。 ### Q: 后端健康检查是如何工作的? **A:** 当前版本(Beta)会在请求失败时标记后端为不可用,并在一段时间后重试。完整的健康检查机制正在开发中。 ### Q: 支持多少个后端? **A:** 理论上没有限制,但建议根据实际场景合理配置(通常 3-10 个后端较为合适)。