# 协议压缩支持 ## 概述 协议栈支持可选的 LZ4 压缩,可以显著减少网络带宽消耗,特别适用于终端输出等重复性较高的数据。 ## 压缩算法选择 我们选择 **LZ4** 作为压缩算法,原因如下: | 特性 | LZ4 | zlib | zstd | |------|-----|------|------| | 压缩速度 | ~500 MB/s | ~50 MB/s | ~300 MB/s | | 解压速度 | ~1500 MB/s | ~250 MB/s | ~800 MB/s | | 压缩比 | 2:1 ~ 3:1 | 3:1 ~ 5:1 | 3:1 ~ 5:1 | | 延迟影响 | 极低 | 中等 | 低 | 对于终端数据流,LZ4 的极低延迟和高速度是最佳选择。 ## 消息头格式 ``` +--------+--------+------------+------------+ | Magic | Type | PayloadLen | Reserved | | 4字节 | 4字节 | 4字节 | 4字节 | +--------+--------+------------+------------+ ``` **Reserved 字段用法:** - **低 16 位**:压缩标志 - bit 0: `MSG_FLAG_COMPRESSED` (0x01) - 载荷已压缩 - bit 1: `MSG_FLAG_COMPRESS_LZ4` (0x02) - 使用 LZ4 压缩 - bit 2: `MSG_FLAG_COMPRESS_HC` (0x04) - 使用高压缩比模式 - **高 16 位**:原始大小 / 256(用于解压缓冲区分配) ## 使用方法 ### C 端 ```c #include "socket_protocol.h" #include "compression.h" // 初始化协议上下文(启用 LZ4 压缩) ProtocolContext ctx; protocol_init(&ctx, COMPRESS_LZ4, 0); // 0 = 默认级别 // 发送压缩消息 write_message_compressed(sock, &ctx, MSG_TYPE_TERMINAL_OUTPUT, data, data_len); // 接收并解压消息 MessageType type; void* payload; uint32_t payload_len, original_len; read_message_decompressed(sock, &type, &payload, &payload_len, &original_len); // 获取压缩统计 uint64_t in, out, count, skip; compression_get_stats(&ctx.compress_ctx, &in, &out, &count, &skip); printf("压缩比: %d%%\n", compression_get_ratio(&ctx.compress_ctx)); ``` ### Go 端 ```go import "go_service/internal/socket" // 创建带压缩的连接 conn := socket.NewConnectionWithCompression(netConn, socket.CompressLZ4, 0) // 或者在现有连接上启用压缩 conn.EnableCompression(socket.CompressLZ4, 0) // 发送压缩消息 ctx := socket.NewCompressionContext(socket.CompressLZ4, 0) socket.WriteMessageCompressed(netConn, ctx, socket.MsgTypeServerResponse, data) // 接收并自动解压 msgType, payload, err := socket.ReadMessageWithDecompression(netConn) // 获取统计信息 bytesIn, bytesOut, compCount, skipCount, ratio := conn.GetCompressionStats() fmt.Printf("压缩比: %d%%\n", ratio) ``` ## 编译配置 ### C 端 ```bash # 安装 LZ4 库 make install-lz4 # 编译(自动检测 LZ4) make # 禁用压缩 make LZ4=0 # 查看是否启用了压缩 make pre_build ``` ### Go 端 LZ4 库会自动通过 `go mod tidy` 安装。 ## 压缩阈值 - 小于 64 字节的数据不会被压缩(开销大于收益) - 如果压缩后数据更大,会自动回退到原始数据 ## 兼容性 - 新版本可以读取旧版本(无压缩)的消息 - 旧版本可以读取新版本的未压缩消息 - 旧版本无法读取压缩消息(会因为 reserved 字段不为 0 而有不同行为,但基本功能仍可工作) ## 性能预期 典型终端场景压缩效果: | 数据类型 | 原始大小 | 压缩后 | 节省 | |----------|----------|--------|------| | ls 输出 | 1000 B | 400 B | 60% | | 代码文件 | 10 KB | 3.5 KB | 65% | | 日志输出 | 5 KB | 1.2 KB | 76% | | 二进制数据 | 1 KB | 900 B | 10% | ## 调试 启用调试模式可以看到压缩详情: ```bash # C 端 make DEBUG=1 # 运行后会输出类似: # [DEBUG] 压缩成功: 1024 -> 412 (40.2%) # [DEBUG] 解压成功: 412 -> 1024 字节 ```