YTFramework-go语言分布式服务器框架
轻量级golang分布式服务器框架,完成了kcp和tcp两种协议的实现
使用nats作为消息中间件
nats和其他消息队列的性能对比:
服务器架构示意图
协议格式TLV-两字节长度,两字节协议id,包体数据
下面是一个简单的快速入门的例子
server.go
package main
import (
"fmt"
"gitee.com/MoGeBingXue/YTFramework/example/chat/protoc"
"gitee.com/MoGeBingXue/YTFramework/net/gameServer"
"gitee.com/MoGeBingXue/YTFramework/net/gate"
"gitee.com/MoGeBingXue/YTFramework/net/netio"
"gitee.com/MoGeBingXue/YTFramework/util/encoder"
"github.com/golang/protobuf/proto"
"github.com/nats-io/nats.go"
)
func main() {
go StartGateServer()
go StartGameServer()
select {}
}
// StartGateServer 开启gate服务器
func StartGateServer() {
info := &gate.GateConfig{Name: "YTServer", Address: "127.0.0.1:8888", NatsURL: nats.DefaultURL, MaxClients: 999, NetioType: netio.Tcp, EncoderType: encoder.ProtobufEncoder}
gate := gate.GetGateServer()
//单起一个进程时,可以阻塞在这儿
<-gate.Start(info)
}
func StartGameServer() {
gs := gameServer.GetGameServer()
gs.Subscribe(1, func(conv uint32, data []byte) {
msg := &protoc.MsgChat{}
err := proto.Unmarshal(data, msg)
if err != nil {
fmt.Println("解析失败")
return
}
fmt.Println("服务端收到了", msg.Msg)
smsg := &protoc.MsgChat{}
smsg.Msg = msg.Msg
//两种实现方式
//sendBytes := gate.Encoder.Encode(1, smsg)
//gs.BroadcastBuffer(sendBytes)
gs.Broadcast(1, smsg)
})
<-gs.Start(&gameServer.GameServerConfig{Name: "gameServer", NatsURL: nats.DefaultURL, EncoderType: encoder.ProtobufEncoder})
}
client.go
package main
import (
"bufio"
"fmt"
"gitee.com/MoGeBingXue/YTFramework/example/chat/protoc"
_interface "gitee.com/MoGeBingXue/YTFramework/net/netio/interface"
"gitee.com/MoGeBingXue/YTFramework/net/netio/tcpio"
"gitee.com/MoGeBingXue/YTFramework/util/encoder/encoder_proto"
"github.com/golang/protobuf/proto"
"os"
)
func main() {
encoder := &encoder_proto.Encoder{}
client := tcpio.NewClient()
client.AddReceiveHandle("onClientReceive", func(peer _interface.Peer, conv uint32, bytes []byte, len int) {
//正常复杂的系统,应该有一个回调函数的map,根据解码出来的ID,调用相应的函数,不同函数是不同的msg类型
rmsg := &protoc.MsgChat{}
//获取长度,由于没有设缓冲区,等价于直接把前两个代表len的byte去掉
//length := int16(bytes[1])<<8 | int16(bytes[0])
//bytes = bytes[2 : length+2]
bytes = bytes[2:]
request, err := encoder.Decode(bytes, conv)
if err != nil {
fmt.Println(err)
return
}
err = proto.Unmarshal(request.Data, rmsg)
if err != nil {
fmt.Println("解析失败")
return
}
fmt.Println("客户端收到了: ", rmsg.Msg)
})
client.Connect("127.0.0.1:8888")
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
smsg := &protoc.MsgChat{}
smsg.Msg = scanner.Text()
sendBytes := encoder.Encode(1, smsg)
client.Send(sendBytes)
}
}