vRp.CD2g_test/server
kercylan98 16704bfbb6 other: 服务器消息优化前 2024-04-07 14:37:56 +08:00
..
client docs: 优化 README.md 可读性 2024-01-15 17:27:02 +08:00
gateway docs: 优化 README.md 可读性 2024-01-15 17:27:02 +08:00
internal other: 服务器消息优化前 2024-04-07 14:37:56 +08:00
lockstep docs: 优化 README.md 可读性 2024-01-15 17:27:02 +08:00
router docs: 优化 README.md 可读性 2024-01-15 17:27:02 +08:00
writeloop docs: 优化 README.md 可读性 2024-01-15 17:27:02 +08:00
README.md docs: 完善根目录 README.md,增加项目实践记录内容。生成子目录 README.md 文档 2024-01-24 11:12:34 +08:00
bot.go feat: server 包新增机器人,可通过 server.NewBot 函数进行创建,机器人将模拟普通连接行为,适用于测试等场景 2023-11-13 16:05:32 +08:00
bot_options.go feat: server 包新增机器人,可通过 server.NewBot 函数进行创建,机器人将模拟普通连接行为,适用于测试等场景 2023-11-13 16:05:32 +08:00
bot_test.go refactor: 移除 slice 包和 hash 包,新增 listings、mappings 包存放数组、切片、映射等数据结构,原 slice、hash 包中的工具函数迁移至 collection 包,与 sher 包合并并移除 sher 包。完善 collection 包测试用例 2024-01-11 17:50:04 +08:00
conn.go feat: 新版 server 包 websocket 基础实现、actor 模型实现 2024-03-21 19:56:33 +08:00
conn_mgr.go test: 完善 dispatcher.Dispatcher 注释及测试用例 2024-01-12 13:48:57 +08:00
conn_packet.go refactor: 调整 server 数据包相关处理函数的接收参数不再为 server.Packet,同时移除 server.Packet 2023-08-23 19:29:55 +08:00
console_params.go feat: 增强 server.RegConsoleCommandEvent 函数,支持 url 格式输入命令,并将命令解析为指令和参数 2023-11-11 19:24:58 +08:00
constants.go feat: server 支持通过 WithLowMessageDuration、WithAsyncLowMessageDuration 函数设置慢消息阈值 2024-01-12 18:43:47 +08:00
doc.go 文档优化 2023-06-12 11:30:08 +08:00
errors.go refactor: server 包重构及性能优化 2023-11-10 18:40:55 +08:00
event.go test: collection 包完善测试用例 2024-01-11 18:46:10 +08:00
gnet.go style: 优化 server 包代码可读性 2023-12-25 17:40:55 +08:00
http.go refactor: 移除过时的 server.NewHttpWrapper 函数、server.Server.HttpServer 函数当需要使用 Gin 相关功能时不再需要通过 Gin 函数获取 2023-12-22 10:17:07 +08:00
http_context.go other: 优化 server 包 http 包装器使用体验 2024-01-05 09:32:14 +08:00
http_router.go feat: server 支持通过 WithLowMessageDuration、WithAsyncLowMessageDuration 函数设置慢消息阈值 2024-01-12 18:43:47 +08:00
http_wrapper.go refactor: 移除过时的 server.NewHttpWrapper 函数、server.Server.HttpServer 函数当需要使用 Gin 相关功能时不再需要通过 Gin 函数获取 2023-12-22 10:17:07 +08:00
http_wrapper_group.go fix: http 包装器 group 修复 2023-08-08 15:05:50 +08:00
listener.go other: server 包部分内容可读性优化,增加健壮度 2023-12-29 12:02:12 +08:00
message.go fix: 修复 server 包死锁检测中 Message 读写的竞态问题 2024-02-22 10:31:59 +08:00
multiple.go feat: server.MultipleServer 支持绑定 Service 2024-01-30 12:39:07 +08:00
multiple_service.go feat: server.MultipleServer 支持绑定 Service 2024-01-30 12:39:07 +08:00
network.go fix: 修复 server 包 WebSocket 路由兼容性问题 2024-02-04 14:01:22 +08:00
options.go feat: server 支持通过 WithLowMessageDuration、WithAsyncLowMessageDuration 函数设置慢消息阈值 2024-01-12 18:43:47 +08:00
options_example_test.go test: server 包完善部分测试用例 2024-01-15 17:27:29 +08:00
options_test.go test: server 包完善部分测试用例 2024-01-15 17:27:29 +08:00
server.go feat: times 包新增 GetWeekdayDateRelativeToNowWithOffset 及 GetWeekdayTimeRelativeToNowWithOffset 函数,用于取代 GetCurrWeekDate 和 GetLastWeekDate 函数 2024-03-18 12:39:26 +08:00
server_example_test.go test: server 包完善部分测试用例 2024-01-15 17:27:29 +08:00
server_test.go test: server 包完善部分测试用例 2024-01-15 17:27:29 +08:00
service.go test: server 包完善部分测试用例 2024-01-15 17:27:29 +08:00
service_example_test.go test: server 包完善部分测试用例 2024-01-15 17:27:29 +08:00
service_test.go test: server 包完善部分测试用例 2024-01-15 17:27:29 +08:00

README.md

Server

Go doc

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 根据特定网络类型创建一个服务器
LoadData 加载绑定的服务器数据
BindData 绑定数据到特定服务器
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 LoadData[T any](srv *Server, name string, data any) T

加载绑定的服务器数据


func BindData(srv *Server, name string, data any)

绑定数据到特定服务器


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
	data                     map[string]any
	messageCounter           atomic.Int64
	addr                     string
	network                  Network
	closed                   uint32
	services                 []func()
}

func (*Server) LoadData(name string, data any) any

加载绑定的服务器数据


func (*Server) BindData(name string, data any)

绑定数据到特定服务器


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)
}