Documentation
¶
Overview ¶
Package jsonstream 实现一套基于 TCP 的 JSON 消息帧协议:定长二进制 帧头承载路由与元信息,载荷为 JSON,单条连接多路复用五种交互模式 (请求/响应、流式、双工通道、单向、发布/订阅),并在传输层参数化 心跳保活、断线重连与会话恢复、flate 压缩、AES-256-GCM 加密与连接级 信用窗口背压。
客户端入口是 Dial,服务端入口是 NewServer;协议规范见 docs/protocol.md,设计权衡见 docs/design-notes.md。
并发模型 ¶
Client 与 Server 的公开方法(注册回调、发起交互、Close 等)均可 被多个 goroutine 并发调用:出站帧经带缓冲通道串行写出,会话与端点 引用有锁保护,Close 幂等且与在途请求竞争时以错误终结全部挂起流。
回调与消费端的边界:
- 流式与双工 handler(HandleStream/HandleChannel 及客户端对称面) 每条流一个 goroutine 顺序执行,handler 内的 Emitter.Emit、 Channel.Send/Receive 无需额外同步;
- ReadStream.Next 与 Channel.Receive 是单消费接口:多个 goroutine 并发调用会互相抢帧(不崩溃,但帧的归属不确定);
- Subscription 的主题回调在内部独占 goroutine 中逐帧串行执行, 回调内可安全调用 Client 的其他方法;
- HandlePublish 与 HandleOneWay 注册的回调每帧一个 goroutine 并发 执行——同一主题高频发布时回调可能同时运行且不保证顺序,需要 顺序或互斥时由回调自行保证。
Index ¶
- Constants
- Variables
- type Channel
- type Client
- func (c *Client) Channel(ctx context.Context, route string, payload any) (*Channel, error)
- func (c *Client) Close() error
- func (c *Client) Handle(route string, h func(*Request) (any, error))
- func (c *Client) HandleChannel(route string, h func(*Channel) error)
- func (c *Client) HandleOneWay(route string, h func(*Message) error)
- func (c *Client) HandleStream(route string, h func(*Request, Emitter) error)
- func (c *Client) OnReconnect(fn func())
- func (c *Client) OnResumeFailed(fn func(error))
- func (c *Client) Publish(ctx context.Context, topic string, payload any) error
- func (c *Client) Request(ctx context.Context, route string, payload any) (*Message, error)
- func (c *Client) SendOneWay(ctx context.Context, route string, payload any) error
- func (c *Client) SessionID() string
- func (c *Client) Stream(ctx context.Context, route string, payload any) (*ReadStream, error)
- func (c *Client) Subscribe(ctx context.Context, topic string, h func(*Message) error) (*Subscription, error)
- type Config
- type ConnectJSON
- type Emitter
- type Error
- type ErrorCode
- type Frame
- type FrameType
- type Header
- type Logger
- type Message
- type ReadStream
- type Request
- type Server
- func (s *Server) Channel(ctx context.Context, sessionID, route string, payload any) (*Channel, error)
- func (s *Server) Close() error
- func (s *Server) Handle(route string, h func(*Request) (any, error))
- func (s *Server) HandleChannel(route string, h func(*Channel) error)
- func (s *Server) HandleOneWay(route string, h func(*Message) error)
- func (s *Server) HandlePublish(topic string, h func(*Message) error)
- func (s *Server) HandleStream(route string, h func(*Request, Emitter) error)
- func (s *Server) OnAuth(h func(*ConnectJSON) error)
- func (s *Server) Publish(ctx context.Context, topic string, payload any) error
- func (s *Server) Request(ctx context.Context, sessionID, route string, payload any) (*Message, error)
- func (s *Server) SendOneWay(ctx context.Context, sessionID, route string, payload any) error
- func (s *Server) Serve() error
- func (s *Server) Sessions() []string
- func (s *Server) Stream(ctx context.Context, sessionID, route string, payload any) (*ReadStream, error)
- type Subscription
Constants ¶
const ( DefaultHeartbeat = 10 * time.Second DefaultRetention = 30 * time.Second DefaultRetentionBytes = 4 << 20 DefaultBackoffInitial = 100 * time.Millisecond DefaultBackoffMax = 5 * time.Second DefaultDialTimeout = 5 * time.Second )
协议参数默认值。
const ( // ProtocolVersion 是当前协议版本。 ProtocolVersion uint8 = 1 // MaxPayloadSize 是单帧载荷(变换后)的上限,超限直接断开以防 OOM。 MaxPayloadSize = 16 << 20 // 16 MiB // MaxMetadataSize 是 Metadata 的上限。线上 metaLen 字段是 uint16, // 恰 64 KiB 的元数据无法表达(编码会截断成 0),故上界为 64 KiB-1。 MaxMetadataSize = math.MaxUint16 // 64 KiB - 1 )
线上帧布局(大端序),见 docs/protocol.md §3:
0 1 Magic "JS" 2 Version 3 Flags 4 Type 5 Reserved 6..9 Stream ID 10..13 Payload Length(变换后字节数) 14..15 Meta Length(仅 Flags.HasMeta)+ Metadata(明文 JSON) ... Payload
const ( FlagCompressed uint8 = 1 << 0 FlagEncrypted uint8 = 1 << 1 FlagHasMeta uint8 = 1 << 2 FlagStream uint8 = 1 << 3 FlagChannel uint8 = 1 << 4 )
Flags 位定义。Stream/Channel 由请求发起方声明,服务端据此校验注册的 handler 类型;Compressed/Encrypted 描述本帧 payload 是否经过对应变换。
Variables ¶
var ErrClosed = errors.New("jsonstream: connection closed")
ErrClosed 表示连接已关闭。
var ErrMalformed = errors.New("jsonstream: malformed frame")
ErrMalformed 表示帧结构损坏(坏魔数、长度越界、截断等)。
Functions ¶
This section is empty.
Types ¶
type Channel ¶
type Channel struct {
// contains filtered or unexported fields
}
Channel 是双工(Flags.Channel)流的两端通用视图:双方都可 Send/Receive,Close 发送 COMPLETE(半关闭:"我说完了"), Cancel 立即终结整条流。Send 可并发调用;Receive 是单消费接口, 在单个 goroutine 中循环调用(见包文档「并发模型」)。
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client 是 JsonStream 客户端:自动重连(指数退避 + 抖动)、会话恢复 (resumed 时保留挂起流等待重放)、断连期间 API 调用挂起而非报错。 公开方法可被多个 goroutine 并发调用(见包文档「并发模型」)。
func Dial ¶
Dial 建立连接并完成握手(阻塞到 CONNACK)。 首连失败(网络不可达或握手被拒)立即返回错误,与常规客户端库直觉一致; 连接成功后的断连才由 connectLoop 自动重连(指数退避 + 抖动,受 Reconnect 控制)。
func (*Client) HandleChannel ¶
HandleChannel 注册双工通道处理器(双向多帧,Close 半关闭)。
func (*Client) HandleOneWay ¶
HandleOneWay 注册单向消息处理器(无应答,错误仅记日志)。
func (*Client) HandleStream ¶
HandleStream 注册服务端发起的流式处理器(Emitter 逐帧下发)。
func (*Client) OnResumeFailed ¶
OnResumeFailed 在会话恢复失败(过期/未知)后回调,应用可据此重建状态。
func (*Client) Publish ¶
Publish 把消息发布到服务端主题(由 Server.HandlePublish 处理)。 ctx 语义与 SendOneWay 相同:约束等连接与等入队两段。
func (*Client) SendOneWay ¶
SendOneWay 单向发送,协议保证不产生任何响应帧。ctx 同时约束「等可用 连接」(断连期间等重连)与「等发送入队」(对端停滞排满发送队列)。
type Config ¶
type Config struct {
// Heartbeat 是 PING 间隔;读空闲超过 1.5 倍即判定断连。零值取默认。
Heartbeat time.Duration
// Compress 启用 flate 压缩(载荷 ≥64B 才实际压缩)。
Compress bool
// Encrypt 启用 AES-256-GCM;启用时 Key 必须是 32 字节。
Encrypt bool
// Key 是预共享密钥(AES-256),不在线上传输。
Key []byte
// Credit >0 时启用连接级信用背压窗口(条数);生效值 = min(双方配置)。
Credit int
// Auth 透传到 CONNECT 的令牌,服务端在握手钩子中校验。
Auth string
// Retention 是服务端断连后的会话保留期;负值禁用会话恢复。
Retention time.Duration
// RetentionBytes 是每会话下行保留队列的字节上限,超限则失去恢复资格。
RetentionBytes int
// DialTimeout 是建立 TCP 连接的超时。
DialTimeout time.Duration
// Reconnect 为 false 时客户端不自动重连(默认 true)。
Reconnect *bool
// BackoffInitial / BackoffMax 是重连退避的起点与上限(指数 + 抖动)。
BackoffInitial time.Duration
BackoffMax time.Duration
// Logger 为 nil 时静默。
Logger Logger
}
Config 是连接两侧共享的协议参数。生效值以 CONNACK 下发的为准 (服务端是权威),字段含义见 docs/protocol.md。
type ConnectJSON ¶
type ConnectJSON struct {
Version int `json:"version"`
Compress bool `json:"compress"`
Encrypt bool `json:"encrypt"`
HeartbeatMS int `json:"heartbeat_ms"`
Credit int `json:"credit,omitempty"`
SessionID string `json:"session_id,omitempty"` // 断线重连时携带
Auth string `json:"auth,omitempty"`
}
ConnectJSON 是 CONNECT 帧的 payload:客户端能力声明与恢复凭证。
type Emitter ¶
Emitter 由流式 handler 用于逐帧下发(受背压约束,额度耗尽时阻塞)。 Emitter 是流式 handler 的下发端:Emit 逐帧发送,handler 正常返回时 自动 COMPLETE。仅在 handler 的 goroutine 内使用(每条流一个 goroutine,见包文档「并发模型」)。
type Error ¶
Error 同时实现标准 error 与错误帧 payload 的编解码载体。
func (*Error) IsProtocol ¶
IsProtocol 报告该错误是否为协议违规(CodeProtocol)。握手与帧层的 协议违规随后断开连接;分发层的 Flags 声明与 handler 模式不符只终结 所在流,连接继续可用(protocol.md §7.10)。
type ErrorCode ¶
type ErrorCode uint8
ErrorCode 是错误帧 payload 中机器可读的错误分类,取值见 docs/protocol.md §7.10。
const ( CodeInternal ErrorCode = 1 // INTERNAL: 处理器内部错误(含 handler panic) CodeNotFound ErrorCode = 2 // NOT_FOUND: 路由不存在 CodeInvalid ErrorCode = 3 // INVALID: 载荷或参数非法 CodeProtocol ErrorCode = 4 // PROTOCOL: 协议违规(必须断开连接) CodeCancelled ErrorCode = 5 // CANCELLED: 对端已取消 CodeTimeout ErrorCode = 6 // TIMEOUT: 处理超时(v1 预留:实现未内置处理超时,无产生路径) CodeAuthDenied ErrorCode = 7 // AUTH_DENIED: 鉴权失败 / 拒绝连接 CodeSessionExpired ErrorCode = 8 // SESSION_EXPIRED: 会话过期,恢复失败 CodeBusy ErrorCode = 9 // BUSY: 过载拒绝(含保留队列溢出) CodeUnsupported ErrorCode = 10 // UNSUPPORTED: 对端未启用的能力被错误使用 )
错误码(§7.10):线上取值即码值,名字映射见 ErrorCode.String。
type Frame ¶
Frame 是内存中的帧。Metadata 恒为明文 JSON(可为 nil); Payload 在协议栈边界内是明文 JSON,读写线上字节时才做压缩/加密变换。
type FrameType ¶
type FrameType uint8
FrameType 帧类型,见 docs/protocol.md §4。
const ( TypeConnect FrameType = 0x01 TypeConnAck FrameType = 0x02 TypePing FrameType = 0x03 TypePong FrameType = 0x04 TypeRequest FrameType = 0x05 TypeResponse FrameType = 0x06 TypeComplete FrameType = 0x07 TypeCancel FrameType = 0x08 TypeOneWay FrameType = 0x09 TypeError FrameType = 0x0A TypeSubscribe FrameType = 0x0B TypeSubAck FrameType = 0x0C TypeUnsubscribe FrameType = 0x0D TypePublish FrameType = 0x0E TypeCredit FrameType = 0x0F )
帧类型(§4):未知类型一律立即断开(不回帧——连帧类型都不认识, 说明对端是异版本实现),为新能力演进留位。
type Message ¶
type Message struct {
StreamID uint32
// Route 是 REQUEST/ONEWAY 的路由名(来自 Metadata)。
Route string
// Topic 是 PUBLISH/SUBSCRIBE 的主题名(来自 Metadata)。
Topic string
Payload json.RawMessage
}
Message 是交付给应用的数据单元:一帧的业务语义视图。
type ReadStream ¶
type ReadStream struct {
// contains filtered or unexported fields
}
ReadStream 是流式响应(Flags.Stream)的读取端。Next 是单消费接口: 在单个 goroutine 中循环调用(见包文档「并发模型」)。
func (*ReadStream) Cancel ¶
func (s *ReadStream) Cancel() error
Cancel 取消流:发 CANCEL 并本地终结。帧经当前 endpoint 发送——会话恢复 迁移后是重连的新连接,构造时的 endpoint 已死(陈旧 ep 引用只会让 CANCEL 静默丢失,对端 handler 永远收不到取消)。
type Request ¶
type Request struct {
*Message
// contains filtered or unexported fields
}
Request 是路由 handler 收到的请求。Context 在所在流被取消/终结后 Done, 长处理可据此提前退出。
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server 是 JsonStream 服务端。路由注册可并发调用,建议在 Serve 之前 完成;运行中注册对新请求立即生效(见包文档「并发模型」)。
func (*Server) Channel ¶
func (s *Server) Channel(ctx context.Context, sessionID, route string, payload any) (*Channel, error)
Channel 向指定会话发起双工通道。
func (*Server) HandleChannel ¶
HandleChannel 注册双工通道路由。
func (*Server) HandleOneWay ¶
HandleOneWay 注册单向路由(永不回帧,路由不存在时静默)。
func (*Server) HandlePublish ¶
HandlePublish 注册客户端发布主题的处理。
func (*Server) HandleStream ¶
HandleStream 注册流式路由。
func (*Server) OnAuth ¶
func (s *Server) OnAuth(h func(*ConnectJSON) error)
OnAuth 注册握手鉴权钩子;返回非 nil error 时以 AUTH_DENIED 拒绝连接。
func (*Server) Publish ¶
Publish 向所有已订阅该主题的连接广播一帧 PUBLISH。ctx 约束每目标 投递的入队等待;取消发生在扇出中途时已投递的目标不撤回,返回 ctx 错误 让调用方知道这次广播是不完整的。
func (*Server) Request ¶
func (s *Server) Request(ctx context.Context, sessionID, route string, payload any) (*Message, error)
Request 向指定会话发起请求/响应。
func (*Server) SendOneWay ¶
SendOneWay 向指定会话单向发送。ctx 约束发送入队等待(sessionEp 本身 非阻塞:只查锁与死连接标志)。
type Subscription ¶
type Subscription struct {
// contains filtered or unexported fields
}
Subscription 是一条主题订阅。回调错误只记日志不回帧(投递方向上 回应会形成"响应的响应",见 docs/protocol.md §7.8)。回调在内部 goroutine 中逐帧串行执行,回调内可安全调用 Client 的其他方法。
func (*Subscription) Close ¶
func (s *Subscription) Close() error
Close 退订:发 UNSUBSCRIBE 并终结本地流。帧必须经当前 endpoint 发送 ——会话恢复后订阅流已迁移到新连接,构造时的旧连接上发送只会得到 ErrClosed,退订帧静默丢失(服务端永远摘不掉该订阅)。
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
client
command
命令 client 是 JsonStream 的示例客户端:依次演示请求/响应、流式响应 (含中途取消)、双工通道、单向发送、发布/订阅与服务端主动发起的应答。
|
命令 client 是 JsonStream 的示例客户端:依次演示请求/响应、流式响应 (含中途取消)、双工通道、单向发送、发布/订阅与服务端主动发起的应答。 |
|
server
command
命令 server 是 JsonStream 的示例服务端:演示请求/响应、流式响应、双工 通道、单向发送、发布/订阅与服务端主动发起。
|
命令 server 是 JsonStream 的示例服务端:演示请求/响应、流式响应、双工 通道、单向发送、发布/订阅与服务端主动发起。 |