LinkAgg - 508364/NetLeaf GitHub Wiki
LinkAgg(Link Aggregation)模块提供同端口链路聚合功能,支持单端口监听并将请求转发到多个后端服务器。
| 状态 | 说明 |
|---|---|
| 版本 | v2.2.1-beta |
| 稳定性 | Beta - 功能完整,但可能存在未发现的问题 |
| 建议 | 生产环境使用前请充分测试 |
| 限制项 | 值 | 说明 |
|---|---|---|
| 最大后端数量 | 512 | 索引范围:0-511 |
| 后端索引 | 0 ~ 511 | 从 0 开始,依次递增 |
// 后端数量限制为 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 (超过最大后端数量)LinkAgg 支持通过 ID 标识不同的服务端口。
ID 必须符合 xxx.xxx 格式(点分隔字符串):
| 格式 | 示例 | 说明 |
|---|---|---|
xxx.xxx |
api.users、web.backend、db.primary
|
必须包含一个点号 |
// 正确的 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 必须唯一
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后端支持 |
-
netleaf (主库)
- 提供 HTTP 服务器和 TCP socket 功能
- LinkAgg 的基础网络层依赖
-
netleaf_ipc (IPC模块)
- 必需依赖,即使不使用 IPC 后端
- 提供进程间通讯能力
- 由于 IPC 模块不支持 macOS,LinkAgg 也不支持 macOS
#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 | 加权轮询,根据权重分配 | 需要按性能分配时 |
// 检查LinkAgg模块是否可用
int nl_linkagg_is_available(void);
// 初始化LinkAgg模块(会自动初始化依赖模块)
int nl_linkagg_init(void);
// 关闭LinkAgg模块
void nl_linkagg_shutdown(void);// 创建链路聚合实例
// 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\<name>, 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);// 获取后端数量
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);// 获取总请求数
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);#include "netleaf_linkagg.h"
#include <stdio.h>
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;
}#include "netleaf_linkagg.h"
#include <stdio.h>
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;
}// 轮询(默认)
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两种后端类型 | ✅ |
| 负载均衡 | 四种负载均衡策略可选 | ✅ |
| 加权分配 | 支持后端权重配置 | ✅ |
| 健康检查 | 自动检测后端健康状态 | |
| 故障转移 | 自动跳过不可用的后端 | |
| 统计信息 | 请求计数和分发统计 | ✅ |
flowchart TD
C["客户端请求"] --> L["LinkAgg 监听端口 (8080)"]
L --> LB["负载均衡器<br/>(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 格式) |
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()if (!nl_linkagg_is_available()) {
// LinkAgg不可用,提供替代方案
printf("LinkAgg requires IPC module, falling back to direct HTTP\n");
}// 根据后端性能设置权重
nl_linkagg_add_http_backend(la, "127.0.0.1", 8081, 2); // 高性能服务器
nl_linkagg_add_http_backend(la, "127.0.0.1", 8082, 1); // 普通服务器// 定期检查后端状态
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);
}
}// 如果使用IPC后端,确保IPC服务已启动
// 否则请求会失败或超时A: LinkAgg 强依赖 IPC 模块,而 IPC 模块不支持 macOS。如需跨平台解决方案,建议使用纯 HTTP 后端。
A: 可以,但 IPC 模块仍然会被加载(作为必需依赖)。如果只是需要 HTTP 负载均衡,也可以考虑其他方案。
A: 当前版本(Beta)会在请求失败时标记后端为不可用,并在一段时间后重试。完整的健康检查机制正在开发中。
A: 理论上没有限制,但建议根据实际场景合理配置(通常 3-10 个后端较为合适)。