due

package module
v0.0.24 Latest Latest
Warning

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

Go to latest
Published: Jul 4, 2023 License: MIT Imports: 12 Imported by: 6

README

due

Build Status goproxy Go Reference Go Report Card Coverage Awesome Go

1.介绍

due是一款基于Go语言开发的轻量级分布式游戏服务器框架。 其中,模块设计方面借鉴了kratos的模块设计思路,为开发者提供了较为灵活的集群构建方案。

架构图

2.优势
  • 简单性:架构简单,源码简洁易理解。
  • 便捷性:仅暴露必要的调用接口,减轻开发者的心智负担。
  • 高效性:框架原生提供tcp、kcp、ws等协议的服务器,方便开发者快速构建各种类型的网关服务器。
  • 扩展性:采用良好的接口设计,方便开发者设计实现自有功能。
  • 平滑性:引入信号量,通过控制服务注册中心来实现优雅地重启。
  • 扩容性:通过优雅的路由分发机制,理论上可实现无限扩容。
  • 易调试:框架原生提供了tcp、kcp、ws等协议的客户端,方便开发者进行独立的调试全流程调试。
  • 可管理:提供完善的后台管理接口,方便开发者快速实现自定义的后台管理功能。
3.功能
  • 网关:支持tcp、kcp、ws等协议的网关服务器。
  • 日志:支持std、zap、logrus、aliyun、tencent等多种日志组件。
  • 注册:支持consul、etcd、k8s、nacos、servicecomb、zookeeper等多种服务注册中心。
  • 协议:支持json、protobuf(gogo/protobuf)、msgpack等多种通信协议。
  • 配置:支持json、yaml、toml、xml等多种文件格式。
  • 通信:支持grpc、rpcx等多种高性能通信方案。
  • 重启:支持服务器的平滑重启。
  • 事件:支持redis、nats、kafka、rabbitMQ等事件总线实现方案。
  • 加密:支持rsa、ecc等多种加密方案。
  • 服务:支持grpc、rpcx等多种微服务解决方案。
  • 灵活:支持单体、分布式等多种架构方案。
  • 管理:提供master后台管理服相关接口支持。

注:出于性能考虑,protobuf协议默认使用gogo/protobuf进行编解码,在生成go代码时请使用gogo库的protoc-gen-xxxx。

go install github.com/gogo/protobuf/protoc-gen-gofast@latest
4.协议

在due框架中,通信协议统一采用route+message的格式:

-------------------------
| seq | route | message |
-------------------------

tcp协议格式:

-------------------------------
| len | seq | route | message |
-------------------------------

说明:

  1. seq表示请求序列号,默认为2字节,常用于请求、响应对的确认。可通过配置文件修改
  2. route表示消息路由,默认为2字节,不同的路由对应不同的业务处理流程。可通过配置文件修改
  3. message表示消息体,采用json或protobuf编码。
  4. 打包器,默认使用小端序编码。可通过配置文件修改
  5. 选择使用tcp协议时,为了解决粘包问题,还应在包前面加上包长度len,固定为4字节,默认使用小端序编码。
5.心跳

很意外,在due框架中,我们并没有采用0号路由来作为默认的心跳包来检测,默认我们采用的空包作为心跳检测包。

设计初衷:不想心跳检测侵入到业务路由层,哪怕是特殊的0号路由。

ws心跳包格式:

[]byte

tcp心跳包格式:

-------
| len |
-------
|  0  |
-------

说明:

  1. ws协议心跳包默认为空bytes。
  2. 选择使用tcp协议时,为了解决粘包问题,还应在包前面加上包长度len,固定为4字节,包长度固定为0。
6.快速开始

下面我们就通过两段简单的代码来体验一下due的魅力,Let's go~~

0.启动组件

docker-compose up

docker-compose.yaml文件已在docker目录中备好,可以直接取用

1.获取框架

go get github.com/dobyte/due@latest
go get github.com/dobyte/due/network/ws@latest
go get github.com/dobyte/due/registry/etcd@latest
go get github.com/dobyte/due/locate/redis@latest
go get github.com/dobyte/due/transport/grpc@latest

2.构建Gate服务器

package main

import (
   "github.com/dobyte/due"
   cluster "github.com/dobyte/due/cluster/gate"
   "github.com/dobyte/due/locate/redis"
   "github.com/dobyte/due/network/ws"
   "github.com/dobyte/due/registry/etcd"
   "github.com/dobyte/due/transport/grpc"
)

func main() {
   // 创建容器
   container := due.NewContainer()
   // 创建网关组件
   gate := cluster.NewGate(
      cluster.WithServer(ws.NewServer()),
      cluster.WithLocator(redis.NewLocator()),
      cluster.WithRegistry(etcd.NewRegistry()),
      cluster.WithTransporter(grpc.NewTransporter()),
   )
   // 添加网关组件
   container.Add(gate)
   // 启动容器
   container.Serve()
}

3.构建Node服务器

package main

import (
   "github.com/dobyte/due"
   cluster "github.com/dobyte/due/cluster/node"
   "github.com/dobyte/due/locate/redis"
   "github.com/dobyte/due/registry/etcd"
   "github.com/dobyte/due/transport/grpc"
)

func main() {
   // 创建容器
   container := due.NewContainer()
   // 创建节点组件
   node := cluster.NewNode(
      cluster.WithLocator(redis.NewLocator()),
      cluster.WithRegistry(etcd.NewRegistry()),
      cluster.WithTransporter(grpc.NewTransporter()),
   )
   // 注册路由
   node.Proxy().Router().AddRouteHandler(1, false, greetHandler)
   // 添加组件
   container.Add(node)
   // 启动服务器
   container.Serve()
}

func greetHandler(ctx *cluster.Context) {
   _ = ctx.Response([]byte("hello world~~"))
}

4.构建Mesh服务

package main

import (
   "context"
   "github.com/dobyte/due"
   cluster "github.com/dobyte/due/cluster/mesh"
   "github.com/dobyte/due/locate/redis"
   "github.com/dobyte/due/log"
   "github.com/dobyte/due/mode"
   "github.com/dobyte/due/registry/consul"
   "github.com/dobyte/due/transport/rpcx"
)

func main() {
   // 开启调试模式
   mode.SetMode(mode.DebugMode)
   // 创建容器
   container := due.NewContainer()
   // 创建网格组件
   mesh := cluster.NewMesh(
      cluster.WithLocator(redis.NewLocator()),
      cluster.WithRegistry(consul.NewRegistry()),
      cluster.WithTransporter(rpcx.NewTransporter()),
   )
   // 初始化业务
   NewWalletService(mesh.Proxy()).Init()
   // 添加网格组件
   container.Add(mesh)
   // 启动容器
   container.Serve()
}

// WalletService 钱包服务
type WalletService struct {
   proxy *cluster.Proxy
}

type IncrGoldRequest struct {
   UID  int64
   Gold int64
}

type IncrGoldReply struct {
}

func NewWalletService(proxy *cluster.Proxy) *WalletService {
   return &WalletService{proxy: proxy}
}

func (w *WalletService) Init() {
   w.proxy.AddServiceProvider("wallet", "Wallet", w)
}

func (w *WalletService) IncrGold(ctx context.Context, req *IncrGoldRequest, reply *IncrGoldReply) error {
   log.Infof("incr %d gold success for uid: %d", req.Gold, req.UID)

   return nil
}

5.构建测试客户端

package main

import (
    "github.com/dobyte/due/config"
    "github.com/dobyte/due/log"
    "github.com/dobyte/due/mode"
    "github.com/dobyte/due/network"
    "github.com/dobyte/due/network/ws"
    "github.com/dobyte/due/packet"
)

var handlers map[int32]handlerFunc

type handlerFunc func(conn network.Conn, buffer []byte)

func init() {
    handlers = map[int32]handlerFunc{
        1: greetHandler,
    }
}

func main() {
    // 创建客户端
    client := ws.NewClient()
    // 监听连接
    client.OnConnect(func(conn network.Conn) {
        log.Infof("connection is opened")
    })
    // 监听断开连接
    client.OnDisconnect(func(conn network.Conn) {
        log.Infof("connection is closed")
    })
    // 监听收到消息
    client.OnReceive(func(conn network.Conn, msg []byte, msgType int) {
        message, err := packet.Unpack(msg)
        if err != nil {
            log.Errorf("unpack message failed: %v", err)
            return
        }

        handler, ok := handlers[message.Route]
        if !ok {
            log.Errorf("the route handler is not registered, route:%v", message.Route)
            return
        }
        handler(conn, message.Buffer)
    })

    conn, err := client.Dial()
    if err != nil {
        log.Fatalf("dial failed: %v", err)
    }

    if err = push(conn, 1, []byte("hello due~~")); err != nil {
        log.Errorf("push message failed: %v", err)
    }

    select {}
}

func greetHandler(conn network.Conn, buffer []byte) {
    log.Infof("received message from server: %s", string(buffer))
}

func push(conn network.Conn, route int32, buffer []byte) error {
    msg, err := packet.Pack(&packet.Message{
        Seq:    1,
        Route:  route,
        Buffer: buffer,
    })
    if err != nil {
        return err
    }

    return conn.Push(msg)
}
7.支持组件
  1. 日志组件
    • zap: github.com/dobyte/due/log/zap
    • logrus: github.com/dobyte/due/log/logrus
    • aliyun: github.com/dobyte/due/log/aliyun
    • tencent: github.com/dobyte/due/log/zap
  2. 网络组件
    • ws: github.com/dobyte/due/network/ws
    • tcp: github.com/dobyte/due/network/tcp
  3. 注册发现
    • etcd: github.com/dobyte/due/registry/etcd
    • consul: github.com/dobyte/due/registry/consul
  4. 传输组件
    • grpc: github.com/dobyte/due/transporter/grpc
    • rpcx: github.com/dobyte/due/transporter/rpcx
  5. 定位组件
    • redis: github.com/dobyte/due/locate/redis
  6. 事件总线
    • redis: github.com/dobyte/due/eventbus/redis
    • nats: github.com/dobyte/due/eventbus/nats
    • kafka: github.com/dobyte/due/eventbus/kafka
8.详细示例

更多详细示例请点击due-example

9.其他客户端

due-client-ts

10.交流与讨论

交流群个人二维码

个人微信:yuebanfuxiao

Documentation

Index

Constants

View Source
const Version = "v0.0.24"

Version 框架版本

View Source
const Website = "https://github.com/dobyte/due"

Website 框架网址

Variables

This section is empty.

Functions

This section is empty.

Types

type Container

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

func NewContainer

func NewContainer() *Container

NewContainer 创建一个容器

func (*Container) Add

func (c *Container) Add(components ...component.Component)

Add 添加组件

func (*Container) Serve

func (c *Container) Serve()

Serve 启动容器

Directories

Path Synopsis
cache
memcache Module
redis Module
consul Module
etcd Module
ecc
rsa
xml
kafka Module
nats Module
redis Module
internal
net
redis Module
locator
redis Module
log
aliyun Module
logrus Module
tencent Module
zap Module
netpoll Module
tcp Module
websocket Module
ws Module
consul Module
etcd Module
grpc Module
rpcx Module
utils

Jump to

Keyboard shortcuts

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