websocketx

package
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 4, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package websocketx 提供独立的标准 http.Handler WebSocket 传输,不依赖 Gin 或消息中间件。 它保持 Text/Binary 消息边界,提供认证、心跳、可选资格复核、有界队列及分阶段关闭。 身份、消息协议、用户/组索引与广播总线由上层业务决定。

基本用法

构造 Endpoint 后挂载普通 HTTP 路由;HTTP 服务和升级后的连接需要分别停止:

endpoint, err := websocketx.New(websocketx.Config{
	MaxConnections: 1000,
	OnMessage: func(ctx context.Context, session *websocketx.Session, message websocketx.Message) error {
		// Text 和 Binary 均完整回送,不修改空白、换行或二进制字节。
		return session.Send(ctx, message)
	},
})
if err != nil {
	return err
}
mux := http.NewServeMux()
mux.Handle("GET /ws", endpoint)
server := &http.Server{
	Addr: ":8080",
	Handler: mux,
	ReadHeaderTimeout: 5 * time.Second,
}
// 应用自行启动 server.ListenAndServe 并接管信号;停机时共享同一个等待期限。
_ = endpoint.Stop()
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
httpErr := server.Shutdown(ctx)
wsErr := endpoint.Wait(ctx)
if wsErr != nil {
	endpoint.Cancel()
}
return errors.Join(httpErr, wsErr)

原始传输默认允许匿名,生产应用可配置 Authenticate 校验凭据并返回不可变 Identity。 AllowedOrigins 默认为完整 scheme/host/port 同源匹配;缺失 Origin 的非浏览器客户端默认允许。 HTTP 的 80、HTTPS 的 443 默认端口省略与显式填写等价;非默认端口仍须匹配。 代理后的外部 Origin 应显式配置,组件不信任 X-Forwarded-*。 RequireSubprotocol 要求至少一个配置子协议被客户端提供,握手失败不会执行业务消息回调。

与 ginx、httpserver 共用端口

三个包在应用层组合:ginx 负责路由,httpserver 负责唯一的端口监听,websocketx 管理升级后的连接。 下例的普通 HTTP 接口 http://localhost:8080/ping 与 WebSocket 地址 ws://localhost:8080/ws 共用端口。 代码放在返回 error 的函数中,需导入 context、errors、net/http、os、os/signal、syscall、time, 以及 github.com/gin-gonic/gin 和 github.com/bpcoder16/pixiu/infra 下的 ginx、httpserver、websocketx:

router, err := ginx.New(ginx.Config{})
if err != nil {
	return err
}
endpoint, err := websocketx.New(websocketx.Config{
	OnMessage: func(ctx context.Context, session *websocketx.Session, message websocketx.Message) error {
		return session.Send(ctx, message)
	},
})
if err != nil {
	return err
}
router.GET("/ping", func(c *gin.Context) {
	c.String(http.StatusOK, "pong")
})
router.GET("/ws", gin.WrapH(endpoint))
server, err := httpserver.New(httpserver.Config{
	Addr: ":8080",
}, router)
if err != nil {
	endpoint.Cancel()
	return err
}
stop, release := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer release()
ran := make(chan error, 1)
go func() { ran <- server.Run() }()
var runErr error
select {
case runErr = <-ran:
case <-stop.Done():
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// 先让两个组件开始停收和排空,再用同一个期限等待。
wsStopErr := endpoint.Stop()
httpStopErr := server.Stop()
httpWaitErr := server.Wait(ctx)
wsWaitErr := endpoint.Wait(ctx)
if httpWaitErr != nil {
	server.Cancel()
}
if wsWaitErr != nil {
	endpoint.Cancel()
}
return errors.Join(runErr, wsStopErr, httpStopErr, httpWaitErr, wsWaitErr)

HTTP 服务不负责回收已升级的 WebSocket 连接,因此两个组件需要分别 Stop/Wait,失败时分别 Cancel。

限额与所有权

默认握手期限 5 秒;认证同步执行,与升级共用期限。回调必须配合 ctx,不得异步保存请求对象。 Session.Context 不继承 HTTP 请求、HTTP Server 或应用信号的取消和可变日志作用域。 OnOpen、每次 OnMessage、Revalidate 均获得独立的日志/计时作用域;业务应使用回调 ctx 调用下游。 OnOpen 与 OnMessage 串行,Revalidate 可与消息处理并发,身份和业务共享状态必须并发安全。

默认收发单条上限各 1 MiB;接收 16 条/4 MiB、发送 64 条/4 MiB,包含在途操作。 默认共享 Budget 接收 128 MiB、发送 1 GiB;多个 Endpoint 只有显式注入同一个 Budget 才共享。 Budget.Usage 和 Session.Usage 是瞬时逻辑占用,包含读取中预留空间,不等于 RSS。 Budget.Limits 返回包含默认值的配置副本,供组合层判断过载恢复水位,不提供运行期改限额。 MaxPendingHandshakes 默认 256,MaxConnections 默认 10000;挂起回调和待收尾连接仍占名额。 默认连接上限按 Endpoint 分别计数,多入口部署须自行分配连接上限并按需共享 Budget。 1 GiB 发送预算可覆盖一轮 10000×64 KiB(625 MiB)逻辑积压;同时多轮仍可能超额。 单条 1 MiB 上限不代表能同时为全部连接积压 1 MiB,预算和连接数须按部署资源显式配置。 默认每 20 秒 Ping、60 秒 Pong 期限、10 秒写入期限、1 秒网络关闭期限。 OnCloseTimeout 默认 5 秒,从清理回调开始执行计时,不是网络关闭期限。 DisableHeartbeat 可显式禁用心跳。MessageTimeout 默认 30 秒,排队时间计入;复核默认每 60 秒执行,期限 5 秒。 数值负值非法;CompressionLevel 零值默认 1,可设置 1–9,压缩仅在 EnableCompression 时协商。

Send/SendPrepared 不等待网络或可用额度,成功只表示本地接纳。输入只在调用期间不可修改,返回后可复用。 SendWhileActive 还在接纳时检查额外的作用域 ctx,可用于限制请求回复的有效期。 Prepare 创建不可变帧;同 Endpoint 的多个连接可并发 SendPrepared,每连接仍扣完整逻辑字节预算。 ExpiresAt 为零时不过期;非零时接纳和实际写入前都检查。晚于入队的 ctx 取消不撤回消息。 ErrQueueFull 表示本连接满,ErrBudgetExceeded 表示共享预算满;组件不自动重试或把它们混为慢客户端。 OnMessage 的 Data 仅在回调期间只读有效,异步使用须自行复制并管理其工作生命周期。

消息大小与性能建议

以高频消息的条数吞吐、CPU 和尾延迟为优先时,建议单条完整消息控制在 1 KiB(1024 字节)以内。 大小按编码后、解压后的消息正文计算:不含 WebSocket 帧头,使用 realtime 时须包含 JSON 协议字段。 该建议来自 M4、Go 1.27.3、双进程各 GOMAXPROCS=4、32 连接、无 TLS/压缩的接收实验, 同时比较原始传输与 realtime + MemoryBus,并提高请求限流以测量饱和吞吐。 本轮 1 KiB 分别保留扫描最高条数吞吐的约 99.8% 和 90.3%;它不是所有业务的全局最优值。 较大消息按业务需要评估 CPU、P99 和积压内存;默认 ReadLimit/MaxSendBytes 仍各为 1 MiB, realtime 默认完整消息上限仍为 64 KiB。

停收与真实完成

StopInput 仅供上层组合:停止新握手、上行数据和新复核,保留已接纳业务和输出。 停收后通过底层读取器跳过未接纳正文,继续处理控制帧;不再解压、校验正文或检查解压后大小。 已开始的读取可继续到本次返回,发现停收后释放其预算并跳过剩余正文;底层帧解析和线上限额仍保留。 通常直接调用 Stop:先停止输入,等存量业务真正返回,再封闭发送、排空并关闭连接。 单独使用 StopInput 必须受有限的整体关闭期限约束:上层排空后调用 Stop/Wait,超时或失败时 Cancel。 与 apprun 一致,各阶段共用关闭期限;Endpoint 不另设停收定时器,也不保证每个阶段都能在 Cancel 前完成。 Wait 只等待真实收尾,超时不取消业务;调用方需要显式 Cancel。 Cancel 不等待网络、业务或观察器;忽略取消的回调继续占用资源,Done 只在其实际返回后关闭。 收尾期间的已知过期、丢弃、写入和回调失败通过 DrainError 汇总;历史失败不污染当前关闭结果。

Session.Close 发起单连接关闭并丢弃未写消息。Detached 表示连接已经不可路由,Done 表示全部收尾完成。 OnDetach 在内部锁外同步执行,只能做快速内存索引清理;它可早于 OnOpen 返回。 网络回收不等待用户钩子,OnClose 等在途业务、读写和复核真实结束后运行一次。 OnClose 的 ctx 不继承会话断连取消;普通断连、Stop 和 Wait 超时不取消清理,Endpoint.Cancel 会取消它。 清理须使用回调 ctx 并配合 OnCloseTimeout/Cancel,实际返回前 Done 不关闭;停收期间清理失败计入 DrainError。 所有回调都不能同步 Wait 自身或所属 Endpoint;Observe 应快速、并发安全,不能代替持久化业务审计。 组件日志/观察仅含元信息,回调错误和 panic 值不会原样进入组件日志。 关闭观察区分正常停机、传输断开、读取超时及协议错误;1006 仅作本地异常断开状态,不发送到网络。 回调自身超时保留 context.DeadlineExceeded,先发生的主动取消保留 context.Canceled。 1000 正常关闭后按时返回 nil 的回调仍算成功;Endpoint.Cancel、关闭故障及实际队列丢弃仍按失败处理。

HTTP Shutdown 不回收已 Hijack 的连接。应用应先完成服务 Stop/Wait 或超时 Cancel, 然后按既有资源栈顺序回收共享客户端,最后关闭日志;不要在资源阶段再次无限等待 Endpoint。

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrClosed 表示连接或 Endpoint 已关闭或当前不接纳该操作。
	ErrClosed = errors.New("websocketx: closed")
	// ErrNilContext 表示调用方传入了 nil context。
	ErrNilContext = errors.New("websocketx: nil context")
	// ErrQueueFull 表示单连接队列额度或 Endpoint 接纳名额不足。
	ErrQueueFull = errors.New("websocketx: connection queue full")
	// ErrBudgetExceeded 表示共享收发预算不足。
	ErrBudgetExceeded = errors.New("websocketx: shared budget exceeded")
	// ErrMessageTooLarge 表示单条消息超过配置的字节上限。
	ErrMessageTooLarge = errors.New("websocketx: message too large")
	// ErrInvalidMessage 表示消息或握手校验失败。
	ErrInvalidMessage = errors.New("websocketx: invalid message")
	// ErrWrongEndpoint 表示预制消息未初始化或属于其他 Endpoint。
	ErrWrongEndpoint = errors.New("websocketx: prepared message belongs to another endpoint")
	// ErrExpired 表示消息已过业务有效期或排队处理期限。
	ErrExpired = errors.New("websocketx: expired")
	// ErrCallback 表示回调失败,用于隐藏原始错误详情。
	ErrCallback = errors.New("websocketx: callback failed")
	// ErrPanic 表示组件捕获到回调 panic。
	ErrPanic = errors.New("websocketx: callback panic")
	// ErrDrainFailed 表示停收后的排空或收尾存在失败,详情见 DrainError。
	ErrDrainFailed = errors.New("websocketx: drain lost work or cleanup failed")
)

Functions

This section is empty.

Types

type Budget

type Budget struct {
	// contains filtered or unexported fields
}

Budget 并发安全,零值使用默认配置;首次使用后不得复制。

func NewBudget

func NewBudget(cfg BudgetConfig) (*Budget, error)

func (*Budget) Limits

func (b *Budget) Limits() BudgetConfig

Limits 返回包含默认值的只读配置副本,供组合层判断过载恢复水位。 条数为零表示不限制;修改返回值不会影响正在使用的预算。

func (*Budget) Usage

func (b *Budget) Usage() Usage

type BudgetConfig

type BudgetConfig struct {
	ReceiveBytes    int64
	SendBytes       int64
	ReceiveMessages int64
	SendMessages    int64
}

BudgetConfig 设置多个 Endpoint 共用的逻辑积压上限。 字节零值默认接收 128 MiB、发送 1 GiB;条数零值不设共享条数上限。

type Config

type Config struct {
	// HandshakeTimeout 是认证与升级共用的期限,默认 5 秒。
	HandshakeTimeout time.Duration
	// ReadLimit 限制正常接收时客户端 → 服务端的单条消息字节数(含解压后),默认 1 MiB。
	// 停收后跳过未接纳正文的解压和大小校验,仍保留底层线上限额。
	ReadLimit int64
	// MaxSendBytes 限制服务端 → 客户端的单条消息正文字节数(按压缩前计算),默认 1 MiB。
	MaxSendBytes int64
	// ReceiveQueueSize 是单连接客户端 → 服务端的累计消息条数上限,默认 16。
	// 包含正在读取组装、排队等待处理和正在派发处理的消息。
	ReceiveQueueSize int
	// ReceiveQueueBytes 是单连接客户端 → 服务端的累计正文字节数上限,默认 4 MiB。
	// 包含读取组装中、排队等待处理和正在派发处理的正文,按解压后字节数计算。
	ReceiveQueueBytes int64
	// SendQueueSize 是单连接服务端 → 客户端的累计消息条数上限,默认 64。
	// 包含排队等待发送和正在写入网络的消息。
	SendQueueSize int
	// SendQueueBytes 是单连接服务端 → 客户端的累计正文字节数上限,默认 4 MiB。
	// 包含排队等待发送和正在写入网络的正文,按压缩前字节数计算。
	SendQueueBytes int64
	// Budget 可供多个 Endpoint 共享;nil 时创建独立的默认预算。
	Budget *Budget
	// MaxPendingHandshakes 是在途握手上限,默认 256。
	MaxPendingHandshakes int
	// MaxConnections 是连接总数上限(含握手和收尾),默认 10000。
	MaxConnections int
	// PingInterval 是主动 Ping 间隔,默认 20 秒,启用心跳时须小于 PongTimeout。
	PingInterval time.Duration
	// PongTimeout 是接收 Pong 的期限,默认 60 秒,每次收到 Pong 后重置。
	PongTimeout time.Duration
	// DisableHeartbeat 默认为 false,即开启心跳。
	// 设为 true 后不主动发送 Ping、不检查 Pong 超时,但仍会回复客户端的 Ping。
	DisableHeartbeat bool
	// WriteTimeout 是出站网络写入期限,默认 10 秒,适用于单条数据消息和主动 Ping。
	// 从实际开始写入时计时,不包含发送队列等待时间;超时或写入失败时发起关闭连接。
	WriteTimeout time.Duration
	// CloseTimeout 是发起连接关闭后发送 Close 控制帧(关闭通知)的期限,默认 1 秒。
	// 通知发送完成、超时或失败后均关闭底层连接;仅控制通知发送,不是整个关闭流程的超时。
	CloseTimeout time.Duration
	// OnCloseTimeout 是 OnClose 清理 context 的期限,默认 5 秒,从回调开始执行计时。
	// 清理不继承会话断连取消,但响应 Endpoint.Cancel;回调须配合取消,实际返回前不关闭 Done。
	OnCloseTimeout time.Duration
	// MessageTimeout 是 OnOpen 初始化和入站消息业务处理的期限,默认 30 秒,不是网络读取超时。
	// OnOpen 从开始执行计时;消息从完整接纳至 OnMessage 返回计时,包含接收队列等待时间。
	// 消息过期或回调超时会发起关闭连接;正在执行的回调须响应 ctx 取消,不能被强制终止。
	MessageTimeout time.Duration
	// RevalidateInterval 是资格复核的基准间隔,默认 60 秒。
	RevalidateInterval time.Duration
	// RevalidateTimeout 是单次资格复核期限,默认 5 秒。
	RevalidateTimeout time.Duration
	// AllowedOrigins 是允许的完整 Origin 列表,空列表默认按 scheme/host/port 校验同源。
	// HTTP 的 80、HTTPS 的 443 默认端口可省略,非默认端口须匹配。
	AllowedOrigins []string
	// AllowAnyOrigin 允许任意合法 Origin,与非空 AllowedOrigins 互斥。
	AllowAnyOrigin bool
	// RejectMissingOrigin 为 true 时拒绝缺失 Origin 的请求,默认允许。
	RejectMissingOrigin bool
	// Subprotocols 是服务端支持的子协议候选列表,按优先级从高到低排列;客户端也可提供多个候选。
	// 按服务端列表顺序选择第一个双方都支持的子协议,匹配成功时仅选定一个,由 Session.Subprotocol() 返回。
	// 无匹配时的服务端行为由 RequireSubprotocol 决定。
	Subprotocols []string
	// RequireSubprotocol 默认为 false,控制服务端是否强制要求协商出子协议。
	// 为 true 时 Subprotocols 不得为空;客户端未提供候选或无匹配时,在升级前返回 HTTP 400。
	// 为 false 时,无匹配不阻止服务端升级,响应不携带 Sec-WebSocket-Protocol,Session.Subprotocol() 返回空字符串。
	RequireSubprotocol bool
	// EnableCompression 为 true 时协商消息压缩,默认关闭。
	EnableCompression bool
	// CompressionLevel 为零时默认 flate.BestSpeed;仅影响启用压缩的连接。
	CompressionLevel int
	// CheckReady 是可选的快速只读接纳门,在锁外调用;false 返回 HTTP 503。
	CheckReady func() bool
	// Authenticate 在握手时认证并生成身份;nil 时允许匿名连接。
	Authenticate func(context.Context, *http.Request) (Identity, error)
	// OnOpen 在认证和 WebSocket 升级成功后、该连接的消息派发前执行。
	// 与 OnMessage 同连接串行;返回错误时关闭连接,不再派发该连接的消息。
	// 单连接回调时序(省略未配置的回调):
	//
	//	Authenticate -> 升级成功 -> OnOpen -> OnMessage -> OnMessage -> ...
	//	                          (同连接串行,Revalidate 可与业务回调并发)
	//
	//	连接建立后的任意阶段触发关闭(可能仍在执行 OnOpen/OnMessage)
	//	  -> 标记关闭、摘除活跃索引、取消 Session.Context、关闭 Detached
	//	  +-> OnDetach -------------------------------------------+
	//	  +-> 关闭网络,等待在途业务、读写和复核结束 -------------+-> OnClose -> 收尾 -> Done
	//
	// 网络回收与 OnDetach 独立推进;两条关闭分支实际结束后才执行 OnClose。
	// 收尾包含关闭观察和释放连接名额,完成后才关闭 Session.Done()。
	// 提前关闭时 OnOpen/OnMessage 可能不执行;握手失败不会进入这些连接回调。
	OnOpen func(context.Context, *Session) error
	// OnMessage 在 OnOpen 成功返回后按连接串行处理完整消息;nil 时丢弃消息。
	OnMessage func(context.Context, *Session, Message) error
	// OnDetach 在连接首次关闭、摘除活跃索引并取消 Session.Context 后调用一次。
	// 此时 Detached 已关闭,但网络和在途 OnOpen/OnMessage/Revalidate 可能尚未结束。
	// 在传输内部锁外同步执行,只做快速内存索引清理,不执行 I/O;
	// 不得在此释放仍被在途回调使用的业务资源,也不得同步等待自身或所属 Endpoint 完成。
	OnDetach func(*Session)
	// OnClose 等网络、在途业务、读写、复核和 OnDetach 全部结束后执行一次。
	// 可在此释放会话业务资源并执行清理 I/O;须使用回调 ctx,不使用已取消的 Session.Context。
	// ctx 独立于会话断连取消,受 OnCloseTimeout(默认 5 秒)及 Endpoint.Cancel 约束。
	// 超时或取消不能强制终止回调,实际返回前 Session.Done 不关闭。
	OnClose func(context.Context, *Session)
	// Revalidate 可与消息处理并发,返回错误时关闭连接;nil 时不启用复核。
	Revalidate func(context.Context, *Session) error
	// Observe 同步、并发安全且应快速返回;事件不携带正文或凭据。
	Observe func(context.Context, Event)
	// Logger 为 nil 时使用 logit.Default,组件不拥有或关闭 Logger。
	Logger logit.Logger
}

Config 配置原始传输,数值零值采用默认值。 回调不能同步等待自身或所属 Endpoint 完成;业务自行等待派生的后台工作。

type DrainError

type DrainError struct {
	ReceiveDropped uint64
	ReceiveExpired uint64
	SendDropped    uint64
	SendExpired    uint64
	WriteErrors    uint64
	// CallbackErrors 统计停收期间传输层回调的失败次数,同一连接可计多次。
	// 上层适配回调收到取消也可能计数,即使它没有调用业务 OnClose。
	CallbackErrors uint64
}

DrainError 汇总首次 StopInput 后的已知失败,不保留正文或无界错误列表。 计数可能覆盖同一消息的不同阶段,不能直接相加作为唯一丢失消息数。

func (*DrainError) Error

func (e *DrainError) Error() string

func (*DrainError) Unwrap

func (e *DrainError) Unwrap() error

type Endpoint

type Endpoint struct {
	// contains filtered or unexported fields
}

Endpoint 是 WebSocket 服务入口,负责握手、会话管理和关闭收尾。 实现 http.Handler,使用 New 构造;不监听端口,也不关闭应用借用的资源。

func New

func New(cfg Config) (*Endpoint, error)
Example
package main

import (
	"context"
	"fmt"
	"net/http/httptest"
	"strings"
	"time"

	"github.com/bpcoder16/pixiu/infra/websocketx"
	"github.com/gorilla/websocket"
)

func main() {
	endpoint, err := websocketx.New(websocketx.Config{
		MaxConnections: 100,
		OnMessage: func(ctx context.Context, session *websocketx.Session, message websocketx.Message) error {
			return session.Send(ctx, message)
		},
	})
	if err != nil {
		panic(err)
	}
	server := httptest.NewServer(endpoint)
	defer server.Close()
	client, _, err := websocket.DefaultDialer.Dial("ws"+strings.TrimPrefix(server.URL, "http"), nil)
	if err != nil {
		panic(err)
	}
	defer client.Close()
	if err := client.WriteMessage(websocket.TextMessage, []byte("hello\nworld")); err != nil {
		panic(err)
	}
	_, text, err := client.ReadMessage()
	if err != nil {
		panic(err)
	}
	fmt.Printf("%q\n", text)
	if err := client.WriteMessage(websocket.BinaryMessage, []byte{0, 255}); err != nil {
		panic(err)
	}
	_, binary, err := client.ReadMessage()
	if err != nil {
		panic(err)
	}
	fmt.Println(binary)
	_ = endpoint.Stop()
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	if err := endpoint.Wait(ctx); err != nil {
		endpoint.Cancel()
		panic(err)
	}
}
Output:
"hello\nworld"
[0 255]

func (*Endpoint) Budget

func (e *Endpoint) Budget() *Budget

func (*Endpoint) Cancel

func (e *Endpoint) Cancel()

Cancel 同步封闭输出、通知取消,网络和回调收尾由已有工作负责。

func (*Endpoint) Done

func (e *Endpoint) Done() <-chan struct{}

func (*Endpoint) Get

func (e *Endpoint) Get(id string) (*Session, bool)

func (*Endpoint) Len

func (e *Endpoint) Len() int

func (*Endpoint) Prepare

func (e *Endpoint) Prepare(message Message) (*PreparedMessage, error)

Prepare 复制一份正文并由 Gorilla 缓存固定编码选项对应的帧;不占发送队列预算。

func (*Endpoint) Range

func (e *Endpoint) Range(fn func(*Session) bool)

Range 锁内获取快照,锁外调用 fn;返回 false 时结束遍历。

func (*Endpoint) ServeHTTP

func (e *Endpoint) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP 的握手同步执行,返回后不再保存或使用 HTTP/Gin 请求对象。

func (*Endpoint) Stop

func (e *Endpoint) Stop() error

Stop 启动唯一收尾任务;不等待业务、网络或观察器。

func (*Endpoint) StopInput

func (e *Endpoint) StopInput() error

StopInput 封闭新握手、数据接纳和新复核;存量业务和输出仍可运行。 未接纳正文由底层跳过,不再解压或校验正文,控制帧继续处理。 调用方必须在有限的整体关闭期限内继续 Stop/Wait,超时或失败时 Cancel;本方法不启动定时关闭。

func (*Endpoint) Wait

func (e *Endpoint) Wait(ctx context.Context) error

Wait 仅等待,不启动关闭,也不把调用方期限传播到业务。

type Event

type Event struct {
	Kind         EventKind
	ConnectionID string
	Type         MessageType
	Bytes        int64
	Duration     time.Duration
	Code         int
	Err          error
	Usage        Usage
}

Event 仅包含元信息;Err 为脱敏的分类错误,不含用户错误文本或 panic 值。 EventClosed 的 Code 可包含仅供本地观察的 1006,Err 可包含读取失败、回调超时及收尾钩子的故障分类。

type EventKind

type EventKind string

EventKind 标识不包含业务正文的传输事件。

const (
	EventHandshake      EventKind = "handshake"
	EventOpened         EventKind = "opened"
	EventReceived       EventKind = "received"
	EventHandled        EventKind = "handled"
	EventSent           EventKind = "sent"
	EventSendDropped    EventKind = "send_dropped"
	EventReceiveDropped EventKind = "receive_dropped"
	EventRevalidated    EventKind = "revalidated"
	EventClosed         EventKind = "closed"
)

type Identity

type Identity struct {
	Subject string
	Value   any
}

Identity 是认证产生的不可变快照,Value 不得包含请求对象、原始凭据或可变共享对象。

type Message

type Message struct {
	Type      MessageType
	Data      []byte
	ExpiresAt time.Time
}

Message 的 Data 在 OnMessage 期间只读有效;Send 返回后调用方可复用输入。 ExpiresAt 为零表示不过期,入站消息不附加业务有效期。

type MessageType

type MessageType int

MessageType 只支持完整的 Text 或 Binary 数据消息,控制帧由组件管理。

const (
	Text   MessageType = 1
	Binary MessageType = 2
)

type PreparedMessage

type PreparedMessage struct {
	// contains filtered or unexported fields
}

PreparedMessage 绑定 Endpoint 和不可变帧,业务不得复用到其他 Endpoint。

type Session

type Session struct {
	// contains filtered or unexported fields
}

Session 由 Endpoint 管理;发送并发安全,身份与连接属性创建后不变。

func (*Session) Close

func (s *Session) Close(code int, reason string) (bool, error)

Close 发起单连接关闭,不排空未写消息;不会等待网络和业务收尾。 OnDetach 在内部锁外同步执行,必须遵守快速内存操作约定。

func (*Session) Context

func (s *Session) Context() context.Context

func (*Session) Detached

func (s *Session) Detached() <-chan struct{}

func (*Session) Done

func (s *Session) Done() <-chan struct{}

func (*Session) ID

func (s *Session) ID() string

func (*Session) Identity

func (s *Session) Identity() Identity

func (*Session) RemoteAddr

func (s *Session) RemoteAddr() string

func (*Session) Send

func (s *Session) Send(ctx context.Context, message Message) error

func (*Session) SendPrepared

func (s *Session) SendPrepared(ctx context.Context, message *PreparedMessage) error

func (*Session) SendWhileActive

func (s *Session) SendWhileActive(ctx, activeCtx context.Context, message Message) error

SendWhileActive 与 Send 共用队列;额外的 activeCtx 非 nil 时也必须在接纳时有效。 入队后任一 context 取消都不会撤回消息。

func (*Session) Subprotocol

func (s *Session) Subprotocol() string

func (*Session) Usage

func (s *Session) Usage() Usage

type Usage

type Usage struct {
	ReceiveMessages int64
	ReceiveBytes    int64
	SendMessages    int64
	SendBytes       int64
}

Usage 包含读取/回调/写入中的占用,不等于进程物理内存。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL