|
||
---|---|---|
.. | ||
client | ||
gateway | ||
internal | ||
lockstep | ||
router | ||
writeloop | ||
README.md | ||
bot.go | ||
bot_options.go | ||
bot_test.go | ||
conn.go | ||
conn_mgr.go | ||
conn_packet.go | ||
console_params.go | ||
constants.go | ||
doc.go | ||
errors.go | ||
event.go | ||
gnet.go | ||
http.go | ||
http_context.go | ||
http_router.go | ||
http_wrapper.go | ||
http_wrapper_group.go | ||
listener.go | ||
message.go | ||
multiple.go | ||
network.go | ||
options.go | ||
options_example_test.go | ||
options_test.go | ||
server.go | ||
server_example_test.go | ||
server_test.go | ||
service.go | ||
service_example_test.go | ||
service_test.go |
README.md
Server
server 提供了包含多种网络类型的服务器实现
目录导航
列出了该 package
下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
展开 / 折叠目录导航
包级函数定义
函数名称 | 描述 |
---|---|
NewBot | 创建一个机器人,目前仅支持 Socket 服务器 |
WithBotNetworkDelay | 设置机器人网络延迟及波动范围 |
WithBotWriter | 设置机器人写入器,默认为 os.Stdout |
DefaultWebsocketUpgrader | 暂无描述... |
NewHttpHandleWrapper | 创建一个新的 http 处理程序包装器 |
NewHttpContext | 基于 gin.Context 创建一个新的 HttpContext |
NewGinWrapper | 创建 gin 包装器,用于对 NewHttpWrapper 函数的替代 |
HasMessageType | 检查是否存在指定的消息类型 |
NewMultipleServer | 暂无描述... |
GetNetworks | 获取所有支持的网络模式 |
WithLowMessageDuration | 通过指定慢消息时长的方式创建服务器,当消息处理时间超过指定时长时,将会输出 WARN 类型的日志 |
WithAsyncLowMessageDuration | 通过指定异步消息的慢消息时长的方式创建服务器,当消息处理时间超过指定时长时,将会输出 WARN 类型的日志 |
WithWebsocketConnInitializer | 通过 websocket 连接初始化的方式创建服务器,当 initializer 返回错误时,服务器将不会处理该连接的后续逻辑 |
WithWebsocketUpgrade | 通过指定 websocket.Upgrader 的方式创建服务器 |
WithConnWriteBufferSize | 通过连接写入缓冲区大小的方式创建服务器 |
WithDispatcherBufferSize | 通过消息分发器缓冲区大小的方式创建服务器 |
WithMessageStatistics | 通过消息统计的方式创建服务器 |
WithPacketWarnSize | 通过数据包大小警告的方式创建服务器,当数据包大小超过指定大小时,将会输出 WARN 类型的日志 |
WithLimitLife | 通过限制最大生命周期的方式创建服务器 |
WithWebsocketWriteCompression | 通过数据写入压缩的方式创建Websocket服务器 |
WithWebsocketCompression | 通过数据压缩的方式创建Websocket服务器 |
WithDeadlockDetect | 通过死锁、死循环、永久阻塞检测的方式创建服务器 |
WithDisableAsyncMessage | 通过禁用异步消息的方式创建服务器 |
WithAsyncPoolSize | 通过指定异步消息池大小的方式创建服务器 |
WithWebsocketReadDeadline | 设置 Websocket 读取超时时间 |
WithTicker | 通过定时器创建服务器,为服务器添加定时器功能 |
WithTLS | 通过安全传输层协议TLS创建服务器 |
WithGRPCServerOptions | 通过GRPC的可选项创建GRPC服务器 |
WithWebsocketMessageType | 设置仅支持特定类型的Websocket消息 |
WithPProf | 通过性能分析工具PProf创建服务器 |
New | 根据特定网络类型创建一个服务器 |
BindService | 绑定服务到特定 Server,被绑定的服务将会在 Server 初始化时执行 Service.OnInit 方法 |
类型定义
类型 | 名称 | 描述 |
---|---|---|
STRUCT |
Bot | 暂无描述... |
STRUCT |
BotOption | 暂无描述... |
STRUCT |
Conn | 服务器连接单次消息的包装 |
STRUCT |
ConsoleParams | 控制台参数 |
STRUCT |
MessageReadyEventHandler | 暂无描述... |
STRUCT |
Http | 基于 gin.Engine 包装的 http 服务器 |
STRUCT |
HttpContext | 基于 gin.Context 的 http 请求上下文 |
STRUCT |
HandlerFunc | 暂无描述... |
STRUCT |
ContextPacker | 暂无描述... |
STRUCT |
HttpRouter | 暂无描述... |
STRUCT |
HttpWrapperHandleFunc | 暂无描述... |
STRUCT |
HttpWrapper | http 包装器 |
STRUCT |
HttpWrapperGroup | http 包装器 |
STRUCT |
MessageType | 暂无描述... |
STRUCT |
Message | 服务器消息 |
STRUCT |
MultipleServer | 暂无描述... |
STRUCT |
Network | 服务器运行的网络模式 |
STRUCT |
Option | 暂无描述... |
STRUCT |
Server | 网络服务器 |
INTERFACE |
Service | 兼容传统 service 设计模式的接口,通过该接口可以实现更简洁、更具有可读性的服务绑定 |
详情信息
func NewBot(srv *Server, options ...BotOption) *Bot
创建一个机器人,目前仅支持 Socket 服务器
查看 / 收起单元测试
func TestNewBot(t *testing.T) {
srv := server.New(server.NetworkWebsocket)
srv.RegConnectionOpenedEvent(func(srv *server.Server, conn *server.Conn) {
t.Logf("connection opened: %s", conn.GetID())
conn.Close()
conn.Write([]byte("hello"))
})
srv.RegConnectionClosedEvent(func(srv *server.Server, conn *server.Conn, err any) {
t.Logf("connection closed: %s", conn.GetID())
})
srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) {
t.Logf("connection %s receive packet: %s", conn.GetID(), string(packet))
conn.Write([]byte("world"))
})
srv.RegStartFinishEvent(func(srv *server.Server) {
bot := server.NewBot(srv, server.WithBotNetworkDelay(100, 20), server.WithBotWriter(func(bot *server.Bot) io.Writer {
return &Writer{t: t, bot: bot}
}))
bot.JoinServer()
time.Sleep(time.Second)
bot.SendPacket([]byte("hello"))
})
_ = srv.Run(":9600")
}
func WithBotNetworkDelay(delay time.Duration, fluctuation time.Duration) BotOption
设置机器人网络延迟及波动范围
- delay 延迟
- fluctuation 波动范围
func WithBotWriter(construction func (bot *Bot) io.Writer) BotOption
设置机器人写入器,默认为 os.Stdout
func DefaultWebsocketUpgrader() *websocket.Upgrader
func NewHttpHandleWrapper[Context any](srv *Server, packer ContextPacker[Context]) *Http[Context]
创建一个新的 http 处理程序包装器
- 默认使用 server.HttpContext 作为上下文,如果需要依赖其作为新的上下文,可以通过 NewHttpContext 创建
func NewHttpContext(ctx *gin.Context) *HttpContext
基于 gin.Context 创建一个新的 HttpContext
func NewGinWrapper[CTX any](server *gin.Engine, pack func (ctx *gin.Context) CTX) *HttpWrapper[CTX]
创建 gin 包装器,用于对 NewHttpWrapper 函数的替代
func HasMessageType(mt MessageType) bool
检查是否存在指定的消息类型
func NewMultipleServer(serverHandle ...func () ((addr string, srv *Server))) *MultipleServer
func GetNetworks() []Network
获取所有支持的网络模式
func WithLowMessageDuration(duration time.Duration) Option
通过指定慢消息时长的方式创建服务器,当消息处理时间超过指定时长时,将会输出 WARN 类型的日志
- 默认值为 DefaultLowMessageDuration
- 当 duration <= 0 时,表示关闭慢消息检测
示例代码:
服务器在启动时将阻塞 1s,模拟了慢消息的过程,这时候如果通过 RegMessageLowExecEvent 函数注册过慢消息事件,将会收到该事件的消息
- 该示例中,将在收到慢消息时关闭服务器
func ExampleWithLowMessageDuration() {
srv := server.New(server.NetworkNone, server.WithLowMessageDuration(time.Second))
srv.RegStartFinishEvent(func(srv *server.Server) {
time.Sleep(time.Second)
})
srv.RegMessageLowExecEvent(func(srv *server.Server, message *server.Message, cost time.Duration) {
srv.Shutdown()
fmt.Println(times.GetSecond(cost))
})
if err := srv.RunNone(); err != nil {
panic(err)
}
}
查看 / 收起单元测试
func TestWithLowMessageDuration(t *testing.T) {
var cases = []struct {
name string
duration time.Duration
}{{name: "TestWithLowMessageDuration", duration: server.DefaultLowMessageDuration}, {name: "TestWithLowMessageDuration_Zero", duration: 0}, {name: "TestWithLowMessageDuration_Negative", duration: -server.DefaultAsyncLowMessageDuration}}
for _, c := range cases {
c := c
t.Run(c.name, func(t *testing.T) {
networks := server.GetNetworks()
for i := 0; i < len(networks); i++ {
low := false
network := networks[i]
srv := server.New(network, server.WithLowMessageDuration(c.duration))
srv.RegMessageLowExecEvent(func(srv *server.Server, message *server.Message, cost time.Duration) {
low = true
srv.Shutdown()
})
srv.RegStartFinishEvent(func(srv *server.Server) {
if c.duration <= 0 {
srv.Shutdown()
return
}
time.Sleep(server.DefaultLowMessageDuration)
})
var lis string
switch network {
case server.NetworkNone, server.NetworkUnix:
lis = "addr"
default:
lis = fmt.Sprintf(":%d", random.UsablePort())
}
if err := srv.Run(lis); err != nil {
t.Fatalf("%s run error: %s", network, err)
}
if !low && c.duration > 0 {
t.Fatalf("%s low message not exec", network)
}
}
})
}
}
func WithAsyncLowMessageDuration(duration time.Duration) Option
通过指定异步消息的慢消息时长的方式创建服务器,当消息处理时间超过指定时长时,将会输出 WARN 类型的日志
- 默认值为 DefaultAsyncLowMessageDuration
- 当 duration <= 0 时,表示关闭慢消息检测
示例代码:
服务器在启动时将发布一条阻塞 1s 的异步消息,模拟了慢消息的过程,这时候如果通过 RegMessageLowExecEvent 函数注册过慢消息事件,将会收到该事件的消息
- 该示例中,将在收到慢消息时关闭服务器
func ExampleWithAsyncLowMessageDuration() {
srv := server.New(server.NetworkNone, server.WithAsyncLowMessageDuration(time.Second))
srv.RegStartFinishEvent(func(srv *server.Server) {
srv.PushAsyncMessage(func() error {
time.Sleep(time.Second)
return nil
}, nil)
})
srv.RegMessageLowExecEvent(func(srv *server.Server, message *server.Message, cost time.Duration) {
srv.Shutdown()
fmt.Println(times.GetSecond(cost))
})
if err := srv.RunNone(); err != nil {
panic(err)
}
}
查看 / 收起单元测试
func TestWithAsyncLowMessageDuration(t *testing.T) {
var cases = []struct {
name string
duration time.Duration
}{{name: "TestWithAsyncLowMessageDuration", duration: time.Millisecond * 100}, {name: "TestWithAsyncLowMessageDuration_Zero", duration: 0}, {name: "TestWithAsyncLowMessageDuration_Negative", duration: -server.DefaultAsyncLowMessageDuration}}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
networks := server.GetNetworks()
for i := 0; i < len(networks); i++ {
low := false
network := networks[i]
srv := server.New(network, server.WithAsyncLowMessageDuration(c.duration))
srv.RegMessageLowExecEvent(func(srv *server.Server, message *server.Message, cost time.Duration) {
low = true
srv.Shutdown()
})
srv.RegStartFinishEvent(func(srv *server.Server) {
if c.duration <= 0 {
srv.Shutdown()
return
}
srv.PushAsyncMessage(func() error {
time.Sleep(c.duration)
return nil
}, nil)
})
var lis string
switch network {
case server.NetworkNone, server.NetworkUnix:
lis = fmt.Sprintf("%s%d", "addr", random.Int(0, 9999))
default:
lis = fmt.Sprintf(":%d", random.UsablePort())
}
if err := srv.Run(lis); err != nil {
t.Fatalf("%s run error: %s", network, err)
}
if !low && c.duration > 0 {
t.Fatalf("%s low message not exec", network)
}
}
})
}
}
func WithWebsocketConnInitializer(initializer func (writer http.ResponseWriter, request *http.Request, conn *websocket.Conn) error) Option
通过 websocket 连接初始化的方式创建服务器,当 initializer 返回错误时,服务器将不会处理该连接的后续逻辑
- 该选项仅在创建 NetworkWebsocket 服务器时有效
func WithWebsocketUpgrade(upgrader *websocket.Upgrader) Option
通过指定 websocket.Upgrader 的方式创建服务器
- 默认值为 DefaultWebsocketUpgrader
- 该选项仅在创建 NetworkWebsocket 服务器时有效
func WithConnWriteBufferSize(size int) Option
通过连接写入缓冲区大小的方式创建服务器
- 默认值为 DefaultConnWriteBufferSize
- 设置合适的缓冲区大小可以提高服务器性能,但是会占用更多的内存
func WithDispatcherBufferSize(size int) Option
通过消息分发器缓冲区大小的方式创建服务器
- 默认值为 DefaultDispatcherBufferSize
- 设置合适的缓冲区大小可以提高服务器性能,但是会占用更多的内存
func WithMessageStatistics(duration time.Duration, limit int) Option
通过消息统计的方式创建服务器
- 默认不开启,当 duration 和 limit 均大于 0 的时候,服务器将记录每 duration 期间的消息数量,并保留最多 limit 条
func WithPacketWarnSize(size int) Option
通过数据包大小警告的方式创建服务器,当数据包大小超过指定大小时,将会输出 WARN 类型的日志
- 默认值为 DefaultPacketWarnSize
- 当 size <= 0 时,表示不设置警告
func WithLimitLife(t time.Duration) Option
通过限制最大生命周期的方式创建服务器
- 通常用于测试服务器,服务器将在到达最大生命周期时自动关闭
func WithWebsocketWriteCompression() Option
通过数据写入压缩的方式创建Websocket服务器
- 默认不开启数据压缩
func WithWebsocketCompression(level int) Option
通过数据压缩的方式创建Websocket服务器
- 默认不开启数据压缩
func WithDeadlockDetect(t time.Duration) Option
通过死锁、死循环、永久阻塞检测的方式创建服务器
- 当检测到死锁、死循环、永久阻塞时,服务器将会生成 WARN 类型的日志,关键字为 "SuspectedDeadlock"
- 默认不开启死锁检测
func WithDisableAsyncMessage() Option
通过禁用异步消息的方式创建服务器
func WithAsyncPoolSize(size int) Option
通过指定异步消息池大小的方式创建服务器
- 当通过 WithDisableAsyncMessage 禁用异步消息时,此选项无效
- 默认值为 DefaultAsyncPoolSize
func WithWebsocketReadDeadline(t time.Duration) Option
设置 Websocket 读取超时时间
- 默认: DefaultWebsocketReadDeadline
- 当 t <= 0 时,表示不设置超时时间
func WithTicker(poolSize int, size int, connSize int, autonomy bool) Option
通过定时器创建服务器,为服务器添加定时器功能
- poolSize:指定服务器定时器池大小,当池子内的定时器数量超出该值后,多余的定时器在释放时将被回收,该值小于等于 0 时将使用 timer.DefaultTickerPoolSize
- size:服务器定时器时间轮大小
- connSize:服务器连接定时器时间轮大小,当该值小于等于 0 的时候,在新连接建立时将不再为其创建定时器
- autonomy:定时器是否独立运行(独立运行的情况下不会作为服务器消息运行,会导致并发问题)
func WithTLS(certFile string, keyFile string) Option
通过安全传输层协议TLS创建服务器
- 支持:Http、Websocket
func WithGRPCServerOptions(options ...grpc.ServerOption) Option
通过GRPC的可选项创建GRPC服务器
func WithWebsocketMessageType(messageTypes ...int) Option
设置仅支持特定类型的Websocket消息
func WithPProf(pattern ...string) Option
通过性能分析工具PProf创建服务器
func New(network Network, options ...Option) *Server
根据特定网络类型创建一个服务器
示例代码:
该案例将创建一个简单的 WebSocket 服务器,如果需要更多的服务器类型可参考 Network
部分
- server.WithLimitLife(time.Millisecond) 通常不是在正常开发应该使用的,在这里只是为了让服务器在启动完成后的 1 毫秒后自动关闭
该案例的输出结果为 true
func ExampleNew() {
srv := server.New(server.NetworkWebsocket, server.WithLimitLife(time.Millisecond))
fmt.Println(srv != nil)
}
查看 / 收起单元测试
该单元测试用于测试以不同的基本参数创建服务器是否存在异常
func TestNew(t *testing.T) {
var cases = []struct {
name string
network server.Network
addr string
shouldPanic bool
}{{name: "TestNew_Unknown", addr: "", network: "Unknown", shouldPanic: true}, {name: "TestNew_None", addr: "", network: server.NetworkNone, shouldPanic: false}, {name: "TestNew_None_Addr", addr: "addr", network: server.NetworkNone, shouldPanic: false}, {name: "TestNew_Tcp_AddrEmpty", addr: "", network: server.NetworkTcp, shouldPanic: true}, {name: "TestNew_Tcp_AddrIllegal", addr: "addr", network: server.NetworkTcp, shouldPanic: true}, {name: "TestNew_Tcp_Addr", addr: ":9999", network: server.NetworkTcp, shouldPanic: false}, {name: "TestNew_Tcp4_AddrEmpty", addr: "", network: server.NetworkTcp4, shouldPanic: true}, {name: "TestNew_Tcp4_AddrIllegal", addr: "addr", network: server.NetworkTcp4, shouldPanic: true}, {name: "TestNew_Tcp4_Addr", addr: ":9999", network: server.NetworkTcp4, shouldPanic: false}, {name: "TestNew_Tcp6_AddrEmpty", addr: "", network: server.NetworkTcp6, shouldPanic: true}, {name: "TestNew_Tcp6_AddrIllegal", addr: "addr", network: server.NetworkTcp6, shouldPanic: true}, {name: "TestNew_Tcp6_Addr", addr: ":9999", network: server.NetworkTcp6, shouldPanic: false}, {name: "TestNew_Udp_AddrEmpty", addr: "", network: server.NetworkUdp, shouldPanic: true}, {name: "TestNew_Udp_AddrIllegal", addr: "addr", network: server.NetworkUdp, shouldPanic: true}, {name: "TestNew_Udp_Addr", addr: ":9999", network: server.NetworkUdp, shouldPanic: false}, {name: "TestNew_Udp4_AddrEmpty", addr: "", network: server.NetworkUdp4, shouldPanic: true}, {name: "TestNew_Udp4_AddrIllegal", addr: "addr", network: server.NetworkUdp4, shouldPanic: true}, {name: "TestNew_Udp4_Addr", addr: ":9999", network: server.NetworkUdp4, shouldPanic: false}, {name: "TestNew_Udp6_AddrEmpty", addr: "", network: server.NetworkUdp6, shouldPanic: true}, {name: "TestNew_Udp6_AddrIllegal", addr: "addr", network: server.NetworkUdp6, shouldPanic: true}, {name: "TestNew_Udp6_Addr", addr: ":9999", network: server.NetworkUdp6, shouldPanic: false}, {name: "TestNew_Unix_AddrEmpty", addr: "", network: server.NetworkUnix, shouldPanic: true}, {name: "TestNew_Unix_AddrIllegal", addr: "addr", network: server.NetworkUnix, shouldPanic: true}, {name: "TestNew_Unix_Addr", addr: "addr", network: server.NetworkUnix, shouldPanic: false}, {name: "TestNew_Websocket_AddrEmpty", addr: "", network: server.NetworkWebsocket, shouldPanic: true}, {name: "TestNew_Websocket_AddrIllegal", addr: "addr", network: server.NetworkWebsocket, shouldPanic: true}, {name: "TestNew_Websocket_Addr", addr: ":9999/ws", network: server.NetworkWebsocket, shouldPanic: false}, {name: "TestNew_Http_AddrEmpty", addr: "", network: server.NetworkHttp, shouldPanic: true}, {name: "TestNew_Http_AddrIllegal", addr: "addr", network: server.NetworkHttp, shouldPanic: true}, {name: "TestNew_Http_Addr", addr: ":9999", network: server.NetworkHttp, shouldPanic: false}, {name: "TestNew_Kcp_AddrEmpty", addr: "", network: server.NetworkKcp, shouldPanic: true}, {name: "TestNew_Kcp_AddrIllegal", addr: "addr", network: server.NetworkKcp, shouldPanic: true}, {name: "TestNew_Kcp_Addr", addr: ":9999", network: server.NetworkKcp, shouldPanic: false}, {name: "TestNew_GRPC_AddrEmpty", addr: "", network: server.NetworkGRPC, shouldPanic: true}, {name: "TestNew_GRPC_AddrIllegal", addr: "addr", network: server.NetworkGRPC, shouldPanic: true}, {name: "TestNew_GRPC_Addr", addr: ":9999", network: server.NetworkGRPC, shouldPanic: false}}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
defer func() {
if err := super.RecoverTransform(recover()); err != nil && !c.shouldPanic {
debug.PrintStack()
t.Fatal("not should panic, err:", err)
}
}()
if err := server.New(c.network, server.WithLimitLife(time.Millisecond*10)).Run(""); err != nil {
panic(err)
}
})
}
}
func BindService(srv *Server, services ...Service)
绑定服务到特定 Server,被绑定的服务将会在 Server 初始化时执行 Service.OnInit 方法
示例代码:
这个案例中我们将 TestService
绑定到了 srv
服务器中,当服务器启动时,将会对 TestService
进行初始化
其中 TestService
的定义如下:
type TestService struct{}
func (ts *TestService) OnInit(srv *server.Server) {
srv.RegStartFinishEvent(onStartFinish)
srv.RegStopEvent(func(srv *server.Server) {
fmt.Println("server stop")
})
}
func (ts *TestService) onStartFinish(srv *server.Server) {
fmt.Println("server start finish")
}
可以看出,在服务初始化时,该服务向服务器注册了启动完成事件及停止事件。这是我们推荐的编码方式,这样编码有以下好处:
- 具备可控制的初始化顺序,避免 init 产生的各种顺序导致的问题,如配置还未加载完成,即开始进行数据库连接等操作
- 可以方便的将不同的服务拆分到不同的包中进行管理
- 当不需要某个服务时,可以直接删除该服务的绑定,而不需要修改其他代码
- ...
func ExampleBindService() {
srv := server.New(server.NetworkNone, server.WithLimitLife(time.Second))
server.BindService(srv, new(TestService))
if err := srv.RunNone(); err != nil {
panic(err)
}
}
查看 / 收起单元测试
func TestBindService(t *testing.T) {
var cases = []struct{ name string }{{name: "TestBindService"}}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
srv := server.New(server.NetworkNone, server.WithLimitLife(time.Millisecond))
server.BindService(srv, new(TestService))
if err := srv.RunNone(); err != nil {
t.Fatal(err)
}
})
}
}
Bot STRUCT
type Bot struct {
conn *Conn
joined atomic.Bool
}
func (*Bot) JoinServer()
加入服务器
func (*Bot) LeaveServer()
离开服务器
func (*Bot) SetNetworkDelay(delay time.Duration, fluctuation time.Duration)
设置网络延迟和波动范围
- delay 延迟
- fluctuation 波动范围
func (*Bot) SetWriter(writer io.Writer)
设置写入器
func (*Bot) SendPacket(packet []byte)
发送数据包到服务器
func (*Bot) SendWSPacket(wst int, packet []byte)
发送 WebSocket 数据包到服务器
BotOption STRUCT
type BotOption func(bot *Bot)
Conn STRUCT
服务器连接单次消息的包装
type Conn struct {
*connection
wst int
ctx context.Context
}
func (*Conn) Ticker() *timer.Ticker
获取定时器
func (*Conn) GetServer() *Server
获取服务器
func (*Conn) GetOpenTime() time.Time
获取连接打开时间
func (*Conn) GetOnlineTime() time.Duration
获取连接在线时长
func (*Conn) GetWebsocketRequest() *http.Request
获取websocket请求
func (*Conn) IsBot() bool
是否是机器人连接
func (*Conn) RemoteAddr() net.Addr
获取远程地址
func (*Conn) GetID() string
获取连接ID
- 为远程地址的字符串形式
func (*Conn) GetIP() string
获取连接IP
func (*Conn) IsClosed() bool
是否已经关闭
func (*Conn) SetData(key any, value any) *Conn
设置连接数据,该数据将在连接关闭前始终存在
func (*Conn) GetData(key any) any
获取连接数据
func (*Conn) ViewData() map[any]any
查看只读的连接数据
func (*Conn) SetMessageData(key any, value any) *Conn
设置消息数据,该数据将在消息处理完成后释放
func (*Conn) GetMessageData(key any) any
获取消息数据
func (*Conn) ReleaseData() *Conn
释放数据
func (*Conn) IsWebsocket() bool
是否是websocket连接
func (*Conn) GetWST() int
获取本次 websocket 消息类型
- 默认将与发送类型相同
func (*Conn) SetWST(wst int) *Conn
设置本次 websocket 消息类型
func (*Conn) PushAsyncMessage(caller func () error, callback func (err error), mark ...log.Field)
推送异步消息,该消息将通过 Server.PushShuntAsyncMessage 函数推送
- mark 为可选的日志标记,当发生异常时,将会在日志中进行体现
func (*Conn) PushUniqueAsyncMessage(name string, caller func () error, callback func (err error), mark ...log.Field)
推送唯一异步消息,该消息将通过 Server.PushUniqueShuntAsyncMessage 函数推送
- mark 为可选的日志标记,当发生异常时,将会在日志中进行体现
- 不同的是当上一个相同的 unique 消息未执行完成时,将会忽略该消息
func (*Conn) Write(packet []byte, callback ...func (err error))
向连接中写入数据
func (*Conn) Close(err ...error)
关闭连接
ConsoleParams STRUCT
控制台参数
type ConsoleParams map[string][]string
func (ConsoleParams) Get(key string) string
获取参数值
func (ConsoleParams) GetValues(key string) []string
获取参数值
func (ConsoleParams) GetValueNum(key string) int
获取参数值数量
func (ConsoleParams) Has(key string) bool
是否存在参数
func (ConsoleParams) Add(key string, value string)
添加参数
func (ConsoleParams) Del(key string)
删除参数
func (ConsoleParams) Clear()
清空参数
MessageReadyEventHandler STRUCT
type MessageReadyEventHandler func(srv *Server)
Http STRUCT
基于 gin.Engine 包装的 http 服务器
type Http[Context any] struct {
srv *Server
*gin.Engine
*HttpRouter[Context]
}
func (*Http) Gin() *gin.Engine
HttpContext STRUCT
基于 gin.Context 的 http 请求上下文
type HttpContext struct {
*gin.Context
}
func (*HttpContext) Gin() *gin.Context
获取 gin.Context
func (*HttpContext) ReadTo(dest any) error
读取请求数据到指定结构体,如果失败则返回错误
HandlerFunc STRUCT
type HandlerFunc[Context any] func(ctx Context)
ContextPacker STRUCT
type ContextPacker[Context any] func(ctx *gin.Context) Context
HttpRouter STRUCT
type HttpRouter[Context any] struct {
srv *Server
group gin.IRouter
packer ContextPacker[Context]
}
func (*HttpRouter) Handle(httpMethod string, relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context]
使用给定的路径和方法注册新的请求句柄和中间件
- 最后一个处理程序应该是真正的处理程序,其他处理程序应该是可以而且应该在不同路由之间共享的中间件。
func (*HttpRouter) POST(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context]
是 Handle("POST", path, handlers) 的快捷方式
func (*HttpRouter) GET(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context]
是 Handle("GET", path, handlers) 的快捷方式
func (*HttpRouter) DELETE(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context]
是 Handle("DELETE", path, handlers) 的快捷方式
func (*HttpRouter) PATCH(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context]
是 Handle("PATCH", path, handlers) 的快捷方式
func (*HttpRouter) PUT(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context]
是 Handle("PUT", path, handlers) 的快捷方式
func (*HttpRouter) OPTIONS(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context]
是 Handle("OPTIONS", path, handlers) 的快捷方式
func (*HttpRouter) HEAD(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context]
是 Handle("HEAD", path, handlers) 的快捷方式
func (*HttpRouter) CONNECT(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context]
是 Handle("CONNECT", path, handlers) 的快捷方式
func (*HttpRouter) TRACE(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context]
是 Handle("TRACE", path, handlers) 的快捷方式
func (*HttpRouter) Any(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context]
注册一个匹配所有 HTTP 方法的路由
- GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE.
func (*HttpRouter) Match(methods []string, relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context]
注册一个匹配指定 HTTP 方法的路由
- GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE.
func (*HttpRouter) StaticFile(relativePath string, filepath string) *HttpRouter[Context]
注册单个路由以便为本地文件系统的单个文件提供服务。
- 例如: StaticFile("favicon.ico", "./resources/favicon.ico")
func (*HttpRouter) StaticFileFS(relativePath string, filepath string, fs http.FileSystem) *HttpRouter[Context]
与
StaticFile
类似,但可以使用自定义的http.FileSystem
代替。
- 例如: StaticFileFS("favicon.ico", "./resources/favicon.ico", Dir{".", false})
- 由于依赖于 gin.Engine 默认情况下使用:gin.Dir
func (*HttpRouter) Static(relativePath string, root string) *HttpRouter[Context]
提供来自给定文件系统根目录的文件。
- 例如: Static("/static", "/var/www")
func (*HttpRouter) StaticFS(relativePath string, fs http.FileSystem) *HttpRouter[Context]
与
Static
类似,但可以使用自定义的http.FileSystem
代替。
- 例如: StaticFS("/static", Dir{"/var/www", false})
- 由于依赖于 gin.Engine 默认情况下使用:gin.Dir
func (*HttpRouter) Group(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context]
创建一个新的路由组。您应该添加所有具有共同中间件的路由。
- 例如: v1 := slf.Group("/v1")
func (*HttpRouter) Use(middleware ...HandlerFunc[Context]) *HttpRouter[Context]
将中间件附加到路由组。
HttpWrapperHandleFunc STRUCT
type HttpWrapperHandleFunc[CTX any] func(ctx CTX)
HttpWrapper STRUCT
http 包装器
type HttpWrapper[CTX any] struct {
server *gin.Engine
packHandle func(ctx *gin.Context) CTX
}
func (*HttpWrapper) Handle(httpMethod string, relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX]
处理请求
func (*HttpWrapper) Use(middleware ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX]
使用中间件
func (*HttpWrapper) GET(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX]
注册 GET 请求
func (*HttpWrapper) POST(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX]
注册 POST 请求
func (*HttpWrapper) DELETE(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX]
注册 DELETE 请求
func (*HttpWrapper) PATCH(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX]
注册 PATCH 请求
func (*HttpWrapper) PUT(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX]
注册 PUT 请求
func (*HttpWrapper) OPTIONS(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX]
注册 OPTIONS 请求
func (*HttpWrapper) HEAD(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX]
注册 HEAD 请求
func (*HttpWrapper) Trace(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX]
注册 Trace 请求
func (*HttpWrapper) Connect(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX]
注册 Connect 请求
func (*HttpWrapper) Any(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX]
注册 Any 请求
func (*HttpWrapper) Match(methods []string, relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX]
注册与您声明的指定方法相匹配的路由。
func (*HttpWrapper) StaticFile(relativePath string, filepath string) *HttpWrapper[CTX]
注册 StaticFile 请求
func (*HttpWrapper) Static(relativePath string, root string) *HttpWrapper[CTX]
注册 Static 请求
func (*HttpWrapper) StaticFS(relativePath string, fs http.FileSystem) *HttpWrapper[CTX]
注册 StaticFS 请求
func (*HttpWrapper) Group(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX]
创建一个新的路由组。您应该添加所有具有共同中间件的路由。
HttpWrapperGroup STRUCT
http 包装器
type HttpWrapperGroup[CTX any] struct {
wrapper *HttpWrapper[CTX]
group *gin.RouterGroup
}
func (*HttpWrapperGroup) Handle(httpMethod string, relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX]
处理请求
func (*HttpWrapperGroup) Use(middleware ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX]
使用中间件
func (*HttpWrapperGroup) GET(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX]
注册 GET 请求
func (*HttpWrapperGroup) POST(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX]
注册 POST 请求
func (*HttpWrapperGroup) DELETE(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX]
注册 DELETE 请求
func (*HttpWrapperGroup) PATCH(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX]
注册 PATCH 请求
func (*HttpWrapperGroup) PUT(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX]
注册 PUT 请求
func (*HttpWrapperGroup) OPTIONS(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX]
注册 OPTIONS 请求
func (*HttpWrapperGroup) Group(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX]
创建分组
MessageType STRUCT
type MessageType byte
func (MessageType) String() string
返回消息类型的字符串表示
Message STRUCT
服务器消息
type Message struct {
dis *dispatcher.Dispatcher[string, *Message]
conn *Conn
err error
ordinaryHandler func()
exceptionHandler func() error
errHandler func(err error)
marks []log.Field
packet []byte
producer string
name string
t MessageType
}
func (*Message) GetProducer() string
func (*Message) MessageType() MessageType
返回消息类型
func (*Message) String() string
返回消息的字符串表示
MultipleServer STRUCT
type MultipleServer struct {
servers []*Server
addresses []string
exitEventHandles []func()
}
func (*MultipleServer) Run()
func (*MultipleServer) RegExitEvent(handle func ())
注册退出事件
func (*MultipleServer) OnExitEvent()
Network STRUCT
服务器运行的网络模式
- 根据不同的网络模式,服务器将会产生不同的行为,该类型将在服务器创建时候指定
服务器支持的网络模式如下:
- NetworkNone 该模式下不监听任何网络端口,仅开启消息队列,适用于纯粹的跨服服务器等情况
- NetworkTcp 该模式下将会监听 TCP 协议的所有地址,包括 IPv4 和 IPv6
- NetworkTcp4 该模式下将会监听 TCP 协议的 IPv4 地址
- NetworkTcp6 该模式下将会监听 TCP 协议的 IPv6 地址
- NetworkUdp 该模式下将会监听 UDP 协议的所有地址,包括 IPv4 和 IPv6
- NetworkUdp4 该模式下将会监听 UDP 协议的 IPv4 地址
- NetworkUdp6 该模式下将会监听 UDP 协议的 IPv6 地址
- NetworkUnix 该模式下将会监听 Unix 协议的地址
- NetworkHttp 该模式下将会监听 HTTP 协议的地址
- NetworkWebsocket 该模式下将会监听 Websocket 协议的地址
- NetworkKcp 该模式下将会监听 KCP 协议的地址
- NetworkGRPC 该模式下将会监听 GRPC 协议的地址
type Network string
func (Network) IsSocket() bool
返回当前服务器的网络模式是否为 Socket 模式,目前为止仅有如下几种模式为 Socket 模式:
- NetworkTcp
- NetworkTcp4
- NetworkTcp6
- NetworkUdp
- NetworkUdp4
- NetworkUdp6
- NetworkUnix
- NetworkKcp
- NetworkWebsocket
Option STRUCT
type Option func(srv *Server)
Server STRUCT
网络服务器
type Server struct {
*event
*runtime
*option
*connMgr
dispatcherMgr *dispatcher.Manager[string, *Message]
ginServer *gin.Engine
httpServer *http.Server
grpcServer *grpc.Server
gServer *gNet
multiple *MultipleServer
ants *ants.Pool
messagePool *hub.ObjectPool[*Message]
ctx context.Context
cancel context.CancelFunc
systemSignal chan os.Signal
closeChannel chan struct{}
multipleRuntimeErrorChan chan error
messageCounter atomic.Int64
addr string
network Network
closed uint32
services []func()
}
func (*Server) Run(addr string) (err error)
使用特定地址运行服务器
- server.NetworkTcp (addr:":8888")
- server.NetworkTcp4 (addr:":8888")
- server.NetworkTcp6 (addr:":8888")
- server.NetworkUdp (addr:":8888")
- server.NetworkUdp4 (addr:":8888")
- server.NetworkUdp6 (addr:":8888")
- server.NetworkUnix (addr:"socketPath")
- server.NetworkHttp (addr:":8888")
- server.NetworkWebsocket (addr:":8888/ws")
- server.NetworkKcp (addr:":8888")
- server.NetworkNone (addr:"")
示例代码:
该案例将创建一个简单的 WebSocket 服务器并启动监听 :9999/
作为 WebSocket 监听地址,如果需要更多的服务器类型可参考 Network
部分
- 当服务器启动失败后,将会返回错误信息并触发 panic
- server.WithLimitLife(time.Millisecond) 通常不是在正常开发应该使用的,在这里只是为了让服务器在启动完成后的 1 毫秒后自动关闭
func ExampleServer_Run() {
srv := server.New(server.NetworkWebsocket, server.WithLimitLife(time.Millisecond))
if err := srv.Run(":9999"); err != nil {
panic(err)
}
}
func (*Server) IsSocket() bool
通过执行 Network.IsSocket 函数检查该服务器是否是 Socket 模式
示例代码:
该案例将创建两个不同类型的服务器,其中 WebSocket 是一个 Socket 服务器,而 Http 是一个非 Socket 服务器
可知案例输出结果为:
- true
- false
func ExampleServer_IsSocket() {
srv1 := server.New(server.NetworkWebsocket)
fmt.Println(srv1.IsSocket())
srv2 := server.New(server.NetworkHttp)
fmt.Println(srv2.IsSocket())
}
查看 / 收起单元测试
这个测试检查了各个类型的服务器是否为 Socket 模式。如需查看为 Socket 模式的网络类型,请参考 Network.IsSocket
func TestServer_IsSocket(t *testing.T) {
var cases = []struct {
name string
network server.Network
expect bool
}{{name: "TestServer_IsSocket_None", network: server.NetworkNone, expect: false}, {name: "TestServer_IsSocket_Tcp", network: server.NetworkTcp, expect: true}, {name: "TestServer_IsSocket_Tcp4", network: server.NetworkTcp4, expect: true}, {name: "TestServer_IsSocket_Tcp6", network: server.NetworkTcp6, expect: true}, {name: "TestServer_IsSocket_Udp", network: server.NetworkUdp, expect: true}, {name: "TestServer_IsSocket_Udp4", network: server.NetworkUdp4, expect: true}, {name: "TestServer_IsSocket_Udp6", network: server.NetworkUdp6, expect: true}, {name: "TestServer_IsSocket_Unix", network: server.NetworkUnix, expect: true}, {name: "TestServer_IsSocket_Http", network: server.NetworkHttp, expect: false}, {name: "TestServer_IsSocket_Websocket", network: server.NetworkWebsocket, expect: true}, {name: "TestServer_IsSocket_Kcp", network: server.NetworkKcp, expect: true}, {name: "TestServer_IsSocket_GRPC", network: server.NetworkGRPC, expect: false}}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
s := server.New(c.network)
if s.IsSocket() != c.expect {
t.Fatalf("expect: %v, got: %v", c.expect, s.IsSocket())
}
})
}
}
func (*Server) RunNone() error
是 Run("") 的简写,仅适用于运行 NetworkNone 服务器
示例代码:
RunNone 函数并没有特殊的意义,该函数内部调用了 srv.Run("")
函数,仅是一个语法糖,用来表示服务器不需要监听任何地址
func ExampleServer_RunNone() {
srv := server.New(server.NetworkNone)
if err := srv.RunNone(); err != nil {
panic(err)
}
}
func (*Server) Context() context.Context
获取服务器上下文
func (*Server) TimeoutContext(timeout time.Duration) ( context.Context, context.CancelFunc)
获取服务器超时上下文,context.WithTimeout 的简写
func (*Server) Ticker() *timer.Ticker
获取服务器定时器
func (*Server) Shutdown()
主动停止运行服务器
func (*Server) GRPCServer() *grpc.Server
当网络类型为 NetworkGRPC 时将被允许获取 grpc 服务器,否则将会发生 panic
func (*Server) HttpRouter() gin.IRouter
当网络类型为 NetworkHttp 时将被允许获取路由器进行路由注册,否则将会发生 panic
- 通过该函数注册的路由将无法在服务器关闭时正常等待请求结束
Deprecated: 从 Minotaur 0.0.29 开始,由于设计原因已弃用,该函数将直接返回 *gin.Server 对象,导致无法正常的对请求结束时进行处理
func (*Server) HttpServer() *Http[*HttpContext]
替代 HttpRouter 的函数,返回一个 *Http[*HttpContext] 对象
- 通过该函数注册的路由将在服务器关闭时正常等待请求结束
- 如果需要自行包装 Context 对象,可以使用 NewHttpHandleWrapper 方法
func (*Server) GetMessageCount() int64
获取当前服务器中消息的数量
func (*Server) UseShunt(conn *Conn, name string)
切换连接所使用的消息分流渠道,当分流渠道 name 不存在时将会创建一个新的分流渠道,否则将会加入已存在的分流渠道
- 默认情况下,所有连接都使用系统通道进行消息分发,当指定消息分流渠道且为分流消息类型时,将会使用指定的消息分流渠道进行消息分发
- 分流渠道会在连接断开时标记为驱逐状态,当分流渠道中的所有消息处理完毕且没有新连接使用时,将会被清除
func (*Server) HasShunt(name string) bool
检查特定消息分流渠道是否存在
func (*Server) GetConnCurrShunt(conn *Conn) string
获取连接当前所使用的消息分流渠道
func (*Server) GetShuntNum() int
获取消息分流渠道数量
func (*Server) PushSystemMessage(handler func (), mark ...log.Field)
向服务器中推送 MessageTypeSystem 消息
- 系统消息仅包含一个可执行函数,将在系统分发器中执行
- mark 为可选的日志标记,当发生异常时,将会在日志中进行体现
func (*Server) PushAsyncMessage(caller func () error, callback func (err error), mark ...log.Field)
向服务器中推送 MessageTypeAsync 消息
- 异步消息将在服务器的异步消息队列中进行处理,处理完成 caller 的阻塞操作后,将会通过系统消息执行 callback 函数
- callback 函数将在异步消息处理完成后进行调用,无论过程是否产生 err,都将被执行,允许为 nil
- 需要注意的是,为了避免并发问题,caller 函数请仅处理阻塞操作,其他操作应该在 callback 函数中进行
- mark 为可选的日志标记,当发生异常时,将会在日志中进行体现
func (*Server) PushShuntAsyncMessage(conn *Conn, caller func () error, callback func (err error), mark ...log.Field)
向特定分发器中推送 MessageTypeAsync 消息,消息执行与 MessageTypeAsync 一致
- 需要注意的是,当未指定 UseShunt 时,将会通过 PushAsyncMessage 进行转发
- mark 为可选的日志标记,当发生异常时,将会在日志中进行体现
func (*Server) PushPacketMessage(conn *Conn, wst int, packet []byte, mark ...log.Field)
向服务器中推送 MessageTypePacket 消息
- 当存在 UseShunt 的选项时,将会根据选项中的 shuntMatcher 进行分发,否则将在系统分发器中处理消息
func (*Server) PushTickerMessage(name string, caller func (), mark ...log.Field)
向服务器中推送 MessageTypeTicker 消息
- 通过该函数推送定时消息,当消息触发时将在系统分发器中处理消息
- 可通过 timer.Ticker 或第三方定时器将执行函数(caller)推送到该消息中进行处理,可有效的避免线程安全问题
- 参数 name 仅用作标识该定时器名称
定时消息执行不会有特殊的处理,仅标记为定时任务,也就是允许将各类函数通过该消息发送处理,但是并不建议
- mark 为可选的日志标记,当发生异常时,将会在日志中进行体现
func (*Server) PushShuntTickerMessage(conn *Conn, name string, caller func (), mark ...log.Field)
向特定分发器中推送 MessageTypeTicker 消息,消息执行与 MessageTypeTicker 一致
- 需要注意的是,当未指定 UseShunt 时,将会通过 PushTickerMessage 进行转发
- mark 为可选的日志标记,当发生异常时,将会在日志中进行体现
func (*Server) PushUniqueAsyncMessage(unique string, caller func () error, callback func (err error), mark ...log.Field)
向服务器中推送 MessageTypeAsync 消息,消息执行与 MessageTypeAsync 一致
- 不同的是当上一个相同的 unique 消息未执行完成时,将会忽略该消息
func (*Server) PushUniqueShuntAsyncMessage(conn *Conn, unique string, caller func () error, callback func (err error), mark ...log.Field)
向特定分发器中推送 MessageTypeAsync 消息,消息执行与 MessageTypeAsync 一致
- 需要注意的是,当未指定 UseShunt 时,将会通过系统分流渠道进行转发
- 不同的是当上一个相同的 unique 消息未执行完成时,将会忽略该消息
func (*Server) PushShuntMessage(conn *Conn, caller func (), mark ...log.Field)
向特定分发器中推送 MessageTypeShunt 消息,消息执行与 MessageTypeSystem 一致,不同的是将会在特定分发器中执行
func (*Server) GetDurationMessageCount() int64
获取当前 WithMessageStatistics 设置的 duration 期间的消息量
func (*Server) GetDurationMessageCountByOffset(offset int) int64
获取特定偏移次数的 WithMessageStatistics 设置的 duration 期间的消息量
- 该值小于 0 时,将与 GetDurationMessageCount 无异,否则将返回 +n 个期间的消息量,例如 duration 为 1 分钟,limit 为 10,那么 offset 为 1 的情况下,获取的则是上一分钟消息量
func (*Server) GetAllDurationMessageCount() []int64
获取所有 WithMessageStatistics 设置的 duration 期间的消息量
func (*Server) HasMessageStatistics() bool
是否了开启消息统计
Service INTERFACE
兼容传统 service 设计模式的接口,通过该接口可以实现更简洁、更具有可读性的服务绑定
- 在这之前,我们在实现功能上会将 Server 进行全局存储,之后通过 init 函数进行初始化,这样的顺序是不可控的。
type Service interface {
OnInit(srv *Server)
}