# 架构重新设计 - 基于最佳实践 ## 设计原则 1. **关注点分离(Separation of Concerns)** - Context:状态管理和流程控制 - Request:数据读取和解码 - Response:数据编码和写入 - Connection:底层网络读写 - Protocol:协议帧头处理 - Codec:数据序列化 2. **现代化API设计** - 精简、直观、类型安全 - 参考Gin、Fiber等框架的设计理念 - 支持链式调用和流畅的API 3. **灵活性** - 支持有帧头协议(如nnet)和无帧头协议(如\n分割) - 支持自定义协议和编解码器 - 支持协议版本管理 ## 核心架构 ### 1. Context(上下文) **职责:** 状态管理和流程控制,不直接处理数据读写 ```go type Context interface { context.Context // 获取Request和Response对象 Request() Request Response() Response Connection() Connection // 状态管理 Set(key string, value interface{}) Get(key string) interface{} MustGet(key string) interface{} } ``` ### 2. Request(请求) **职责:** 数据读取、协议解码、编解码器解码 ```go type Request interface { // 原始数据(未解码的字节) Raw() []byte // 协议解码后的数据(去除帧头后的字节) Data() []byte // 解码为Go对象(经过protocol decode + codec decode) Decode(v interface{}) error DecodeWithCodec(v interface{}, codecName string) error // 协议帧头(如果有) Header() FrameHeader // 协议信息 Protocol() Protocol ProtocolVersion() string } ``` ### 3. Response(响应) **职责:** 数据编码、协议编码、数据写入 ```go type Response interface { // 写入数据(自动编码) Write(data interface{}) error WriteWithCodec(data interface{}, codecName string) error // 写入原始字节(绕过编码) WriteBytes(data []byte) error WriteString(s string) error // 协议帧头操作(如果有) SetHeader(header FrameHeader) error Header() FrameHeader // 发送响应(如果使用缓冲模式) Send() error } ``` ### 4. FrameHeader(协议帧头) **职责:** 协议帧头的数据结构 ```go type FrameHeader interface { // 获取帧头字段 Get(key string) interface{} Set(key string, value interface{}) // 编码为字节 Encode() ([]byte, error) // 从字节解码 Decode(data []byte) error } ``` ### 5. Protocol(协议) **职责:** 协议帧头的编码和解码 ```go type Protocol interface { Name() string Version() string // 编码(添加帧头) Encode(data []byte, header FrameHeader) ([]byte, error) // 解码(提取帧头和数据) Decode(data []byte) (FrameHeader, []byte, error) // 是否有帧头(无帧头协议返回false) HasHeader() bool } ``` ## 数据流程 ### 读数据流程 ``` 1. Connection.Read() → []byte (原始字节) ↓ 2. Protocol.Decode() → FrameHeader + []byte (帧头 + 数据) ↓ 3. Codec.Decode() → interface{} (Go对象) ↓ 4. Request.Decode() → 提供给处理器使用 ``` ### 写数据流程 ``` 1. Response.Write(interface{}) → Go对象 ↓ 2. Codec.Encode() → []byte (序列化后的数据) ↓ 3. Protocol.Encode() → []byte (添加帧头) ↓ 4. Connection.Write() → 发送到客户端 ``` ## 无帧头协议支持 对于无帧头协议(如\n分割),Protocol实现: ```go type NoHeaderProtocol struct{} func (p *NoHeaderProtocol) HasHeader() bool { return false // 无帧头 } func (p *NoHeaderProtocol) Encode(data []byte, header FrameHeader) ([]byte, error) { // 无帧头协议,直接返回数据,可能添加分隔符 return append(data, '\n'), nil } func (p *NoHeaderProtocol) Decode(data []byte) (FrameHeader, []byte, error) { // 无帧头协议,直接返回数据(去除分隔符) data = bytes.TrimSuffix(data, []byte{'\n'}) return nil, data, nil // 返回nil header } ``` ## API设计示例 ### 基本使用 ```go // 处理器 func handler(ctx context.Context) error { req := ctx.Request() resp := ctx.Response() // 读取请求(自动解码) var requestData MyRequest if err := req.Decode(&requestData); err != nil { return err } // 处理业务逻辑 responseData := MyResponse{ Code: 200, Data: "success", } // 写入响应(自动编码) return resp.Write(responseData) } ``` ### 自定义协议帧头 ```go func handler(ctx context.Context) error { req := ctx.Request() resp := ctx.Response() // 读取协议帧头 header := req.Header() if header != nil { messageType := header.Get("message_type") // 使用帧头信息 } // 读取数据 var data MyData req.Decode(&data) // 设置响应帧头 respHeader := NewFrameHeader() respHeader.Set("message_type", 0x01) resp.SetHeader(respHeader) // 写入响应 return resp.Write(MyResponse{Code: 200}) } ``` ### 无帧头协议 ```go func handler(ctx context.Context) error { req := ctx.Request() resp := ctx.Response() // 无帧头协议,直接读取原始数据 rawData := req.Data() // 或 req.Raw() // 处理数据 result := processData(rawData) // 写入响应(协议会自动添加\n) return resp.WriteString(result) } ``` ### 指定编解码器 ```go func handler(ctx context.Context) error { req := ctx.Request() resp := ctx.Response() // 使用指定的编解码器解码 var data MyData req.DecodeWithCodec(&data, "msgpack") // 使用指定的编解码器编码 return resp.WriteWithCodec(MyResponse{Code: 200}, "msgpack") } ``` ## 配置设计 ```go type Config struct { // 协议配置 Protocol struct { Name string // 协议名称 Version string // 协议版本 HasHeader bool // 是否有帧头 } // 编解码器配置 Codec struct { Default string // 默认编解码器 } } ``` ## 路由集成 路由匹配可以在不同层次进行: 1. **协议层匹配**:根据协议帧头匹配(如果有) 2. **数据层匹配**:根据解码后的数据匹配 3. **原始数据匹配**:根据原始字节匹配(无帧头协议) ## 实现计划 ### 第一阶段:核心接口定义 1. 定义Context、Request、Response接口 2. 定义FrameHeader接口 3. 更新Protocol接口 ### 第二阶段:实现Request和Response 1. 实现Request的读取和解码功能 2. 实现Response的编码和写入功能 3. 集成协议和编解码器 ### 第三阶段:更新Context 1. 移除Context中的数据读写方法 2. 添加Request和Response对象 3. 更新所有使用Context的地方 ### 第四阶段:更新服务器 1. 更新服务器中的数据流程 2. 实现协议解码逻辑 3. 实现协议编码逻辑 ### 第五阶段:测试和优化 1. 编写测试用例 2. 性能优化 3. 文档更新 ## 优势 1. **清晰的职责分离**:每个组件职责明确 2. **灵活的扩展性**:支持各种协议和编解码器 3. **现代化的API**:简洁、直观、类型安全 4. **向后兼容**:可以逐步迁移现有代码 5. **最佳实践**:参考了主流框架的设计理念