Awesome Go

due

CategoryGame Development
SubcategoryGame Development
Stars965

Distributed game server framework with a modular component design, providing tcp, kcp, ws and quic gateways

About due

This large README is shown as a plain-text preview. Read the full README at the source

# due — A High-Performance Distributed Game Server Framework in Go

English | [简体中文](README-ZH.md)

[![Build Status](https://github.com/dobyte/due/workflows/Go/badge.svg)](https://github.com/dobyte/due/actions)
[![Go Version](https://img.shields.io/github/go-mod/go-version/dobyte/due)](https://github.com/dobyte/due)
[![Go Reference](https://pkg.go.dev/badge/github.com/dobyte/due/v2.svg)](https://pkg.go.dev/github.com/dobyte/due/v2)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Go Report Card](https://goreportcard.com/badge/github.com/dobyte/due)](https://goreportcard.com/report/github.com/dobyte/due)
[![codecov](https://codecov.io/gh/dobyte/due/branch/main/graph/badge.svg)](https://codecov.io/gh/dobyte/due)
[![Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)

[![Release](https://img.shields.io/github/v/release/dobyte/due?style=flat)](https://github.com/dobyte/due/releases)
![Stars](https://img.shields.io/github/stars/dobyte/due?style=flat)
![Forks](https://img.shields.io/github/forks/dobyte/due?style=flat)
[![GitHub pull requests](https://img.shields.io/github/issues-pr/dobyte/due?style=flat)](https://github.com/dobyte/due/pulls)
[![GitHub closed pull requests](https://img.shields.io/github/issues-pr-closed/dobyte/due?style=flat)](https://github.com/dobyte/due/pulls?q=is%3Apr+is%3Aclosed)
[![GitHub issues](https://img.shields.io/github/issues/dobyte/due?style=flat)](https://github.com/dobyte/due/issues)
[![GitHub closed issues](https://img.shields.io/github/issues-closed/dobyte/due?style=flat)](https://github.com/dobyte/due/issues?q=is%3Aissue+is%3Aclosed)

### 1. Introduction

[due](https://dobyte.github.io/) is a lightweight, high-performance distributed game server framework developed in Go.
Its module design draws on the modular design philosophy of [kratos](https://github.com/go-kratos/kratos), aiming to provide a complete, efficient, elegant, and standardized solution for game server development.
Since its creation, the framework has been deployed and battle-tested in multiple enterprise-level game projects, with stability fully guaranteed.

![Architecture](architecture.jpg)

### 2. Advantages

* 💰 Free: The framework follows the MIT license and is fully open-source and free.
* 💡 Simplicity: Simple architecture with concise, easy-to-understand source code.
* 🚠 Convenience: Only the necessary APIs are exposed, reducing the mental burden on developers.
* 🚀 High performance: The framework natively implements a cluster communication solution; a single thread on an ordinary machine can easily achieve 430K TPS.
* 🧊 Standardization: The framework natively provides standardized development conventions, making even the most complex projects easy to handle.
* ✈️ Efficiency: The framework natively provides tcp, kcp, ws, quic and other servers, making it easy for developers to quickly build various types of gateway servers.
* ⚖️ Stability: All official releases have passed rigorous testing in real internal business scenarios, offering high stability.
* 🎟️ Extensibility: Well-designed interfaces make it easy for developers to design and implement their own features.
* 🔑 Smoothness: Semaphores are introduced to enable graceful rolling updates by controlling the service registry.
* 🔩 Scalability: A graceful route-dispatch mechanism theoretically enables unlimited horizontal scaling.
* 🔧 Easy debugging: The framework natively provides tcp, kcp, ws, quic and other clients, making it easy for developers to perform independent end-to-end debugging.
* 🧰 Manageability: Complete admin APIs make it easy for developers to quickly build custom admin functionality.

### 3. Features

* Gateway: Gateway servers supporting protocols such as tcp, kcp, ws, and quic.
* Logging: Multiple logging components such as console, file, aliyun, and tencent.
* Registry: Multiple service registries such as etcd, consul, nacos, and polaris.
* Protocol: Multiple communication protocols such as json, protobuf, msgpack, xml, yaml, and toml.
* Configuration: Multiple config centers such as file, etcd, consul, nacos, and polaris; also supports file formats such as json, yaml, toml, and xml.
* Communication: Multiple high-performance communication solutions such as grpc and rpcx.
* Restart: Graceful restart of servers.
* Event: Event bus implementations such as process, redis, nats, and kafka.
* Encryption: Multiple encryption and signature schemes such as rsa and ecc.
* Service: Multiple microservice solutions such as grpc and rpcx.
* Flexible: Multiple architecture options such as monolithic and distributed.
* Web: Provides a fiber server for the http protocol and a swagger documentation solution.
* Tooling: Provides the [due-cli](https://github.com/dobyte/due-cli) scaffolding toolbox to quickly build cluster projects.
* Cache: Multiple commonly used caching solutions such as redis and memcache.
* Actor: Provides a complete actor model solution.
* Distributed lock: Multiple distributed lock solutions such as redis and memcache.
* Network: Servers and clients supporting the four protocols tcp, kcp, ws, and quic, with unified heartbeat, authorization, graceful shutdown, and connection management capabilities.

> Next up: a distributed task scheduling system.

### 4. Architecture and Core Concepts

#### 4.1 Components and Container

due adopts a modular "container + component" design. The framework abstracts the gate, node, mesh, cluster client, as well as logging, HTTP, pprof and other capabilities into components (Component), whose lifecycle is orchestrated uniformly by the container (Container):

```go
type Component interface {
    Name() string // component name
    Init()        // initialize the component
    Start()       // start the component
    Close()       // close the component
    Destroy()     // destroy the component
}

func main() {
    container := due.NewContainer() // create a container
    container.Add(component)        // add a component; can be called multiple times
    container.Serve()               // start the container and wait for system signals
}
```

The execution order of `Serve` is: print framework information → `Init` each component in order → `Start` each component in order → write the PID file → wait for system signals → `Close` components concurrently → `Destroy` components concurrently → clean up the PID and global modules.

* Signal handling: Windows listens for `os.Interrupt`; other systems listen for `SIGINT`, `SIGQUIT`, `SIGABRT`, and `SIGTERM`.
* Shutdown timeout: the `Close` phase is controlled by `etc.shutdownMaxWaitTime`; the `Destroy` phase has a fixed 5-second timeout.
* Graceful restart: during the `Close` phase, Gate/Node/Mesh set their own state to `hang` and refresh the instance state in the registry, so that new traffic no longer enters the instance, while waiting for existing sessions and messages to be fully processed. The actual deregistration happens in the `Destroy` phase. Combined with semaphores, this enables rolling updates.

#### 4.2 Instance Kind

| Constant | Value | String | Description |
| --- | --- | --- | --- |
| `cluster.Gate` | 1 | gate | Gateway server |
| `cluster.Node` | 2 | node | Node server |
| `cluster.Mesh` | 3 | mesh | Microservice |
| `cluster.Master` | 4 | master | Admin server |

#### 4.3 Instance State

| Constant | Value | String | Description |
| --- | --- | --- | --- |
| `cluster.Shut` | 0 | shut | Shut down |
| `cluster.Work` | 1 | work | Working |
| `cluster.Busy` | 2 | busy | Busy |
| `cluster.Hang` | 3 | hang | Hanging |

> The gateway accepts new client connections only in the `work` and `busy` states; in all other states it closes the connection immediately.

#### 4.4 Lifecycle Hook

| Constant | Value | Description |
| --- | --- | --- |
| `cluster.Init` | 0 | Initialize the component |
| `cluster.Start` | 1 | Start the component |
| `cluster.Close` | 2 | Close the component |
| `cluster.Destroy` | 3 | Destroy the component |

The node, mesh, and cluster client components can listen to their own lifecycle via `Proxy.AddHookListener(hook, handler)`, which is commonly used for initialization work such as establishing connections after the component starts.

#### 4.5 Event Type

| Constant | Value | Description |
| --- | --- | --- |
| `cluster.Connect` | 1 | Connection opened |
| `cluster.Reconnect` | 2 | Reconnected after disconnection |
| `cluster.Disconnect` | 3 | Connection closed |

#### 4.6 Dispatch Strategy

Load dispatch strategies between cluster instances:

| Constant | Value | Description |
| --- | --- | --- |
| `cluster.Random` | random | Random |
| `cluster.RoundRobin` | rr | Round robin |
| `cluster.WeightedRoundRobin` | wrr | Weighted round robin |

The cluster's internal transport layer (grpc/rpcx) additionally supports a consistent-hash strategy (`ch`), which pins calls with the same request characteristics to the same instance.

#### 4.7 Gate, Node, Mesh, and Client

> Members of the due community frequently ask about the relationship among Gate, Node, and Mesh, so here is a unified explanation.

* Gate: The gateway server, mainly used to manage client connections, receive routed messages from clients, and dispatch routed messages to different Node servers.
* Node: The node server, the core component of the entire cluster system, mainly used to write core business logic. Node services can be stateful or stateless as needed. As a stateless node, a Node is essentially no different from a Mesh microservice; but as a stateful node, a Node cannot be updated and restarted freely. This is where the value of separating Node from Mesh comes in.
* Mesh: The microservice, mainly used to write stateless business logic. Anything Mesh can do, Node can do as well; the choice depends entirely on your own business scenario, and developers can combine them flexibly.
* Client: The cluster client component, which can dial the gateway directly. It is convenient for writing automated tests, stress-test programs, or bot logic within a server project, enabling independent end-to-end debugging.

### 5. Project Structure

```text
due/
├── container.go            Container entry (the only source file in the root package)
├── cluster/                Cluster components
│   ├── cluster.go          Cluster model: Kind/State/Event/Hook/Dispatch and cluster message structures
│   ├── gate/               Gateway component
│   ├── node/               Node component (routing, events, actor model)
│   ├── mesh/               Microservice component
│   └── client/             Cluster client component
├── network/                Network module: tcp, kcp, ws, quic
├── session/                Gateway session management: connection sessions, user sessions, and channel subscriptions
├── packet/                 Communication protocol packing: Packer and Message
├── internal/               Internal implementation: cluster linker, instance dispatcher, intranet RPC protocol
├── registry/               Registries: etcd, consul, nacos, polaris
├── config/                 Config centers: file, etcd, consul, nacos, polaris
├── locate/                 User location: redis
├── transport/              Internal cluster transport: grpc, rpcx
├── eventbus/               Event buses: process, redis, nats, kafka
├── cache/                  Caches: redis, memcache
├── lock/                   Distributed locks: redis, memcache
├── crypto/                 Encryption/decryption and signatures: rsa, ecc
├── encoding/               Codecs: json, proto, msgpack, xml, yaml, toml
├── log/                    Logging: console, file, aliyun, tencent
├── component/              Built-in components: http, mqtt, pprof
├── core/                   Core foundation library: buffer, queue, value, stack, limiter, etc.
├── utils/                  Utility library: xcall, xconv, xnet, xtime, xhash, etc.
├── codes/, errors/         Error codes and error definitions
├── mode/, flag/, env/, etc/  Run mode, command-line flags, environment variables, and startup configuration
├── task/                   Global task pool and task groups
├── docker/                 Middleware orchestration (docker-compose.yaml)
├── benchmark/              Stress-test project (a separate Go module)
└── testdata/               Example configuration and test data
```

### 6. Module List

The framework is published as multiple modules: the core capabilities live in the main module `github.com/dobyte/due/v2`, while pluggable components are each an independent module, making it easy to import them on demand.

| Category | Component | Import Path |
| --- | --- | --- |
| Core | Framework main module | `github.com/dobyte/due/v2` |
| Network | tcp | `github.com/dobyte/due/network/tcp/v2` |
| Network | kcp | `github.com/dobyte/due/network/kcp/v2` |
| Network | ws | `github.com/dobyte/due/network/ws/v2` |
| Network | quic | `github.com/dobyte/due/network/quic/v2` |
| Registry | etcd | `github.com/dobyte/due/registry/etcd/v2` |
| Registry | consul | `github.com/dobyte/due/registry/consul/v2` |
| Registry | nacos | `github.com/dobyte/due/registry/nacos/v2` |
| Registry | polaris | `github.com/dobyte/due/registry/polaris/v2` |
| Config Center | file (built-in) | `github.com/dobyte/due/v2/config/file` |
| Config Center | etcd | `github.com/dobyte/due/config/etcd/v2` |
| Config Center | consul | `github.com/dobyte/due/config/consul/v2` |
| Config Center | nacos | `github.com/dobyte/due/config/nacos/v2` |
| Config Center | polaris | `github.com/dobyte/due/config/polaris/v2` |
| Location | redis | `github.com/dobyte/due/locate/redis/v2` |
| Transport | grpc | `github.com/dobyte/due/transport/grpc/v2` |
| Transport | rpcx | `github.com/dobyte/due/transport/rpcx/v2` |
| Event Bus | process (built-in) | `github.com/dobyte/due/v2/eventbus/process` |
| Event Bus | redis | `github.com/dobyte/due/eventbus/redis/v2` |
| Event Bus | nats | `github.com/dobyte/due/eventbus/nats/v2` |
| Event Bus | kafka | `github.com/dobyte/due/eventbus/kafka/v2` |
| Cache | redis | `github.com/dobyte/due/cache/redis/v2` |
| Cache | memcache | `github.com/dobyte/due/cache/memcache/v2` |
| Distributed Lock | redis | `github.com/dobyte/due/lock/redis/v2` |
| Distributed Lock | memcache | `github.com/dobyte/due/lock/memcache/v2` |
| Crypto | rsa | `github.com/dobyte/due/crypto/rsa/v2` |
| Crypto | ecc | `github.com/dobyte/due/crypto/ecc/v2` |
| Logging | console (built-in) | `github.com/dobyte/due/v2/log/console` |
| Logging | file (built-in) | `github.com/dobyte/due/v2/log/file` |
| Logging | aliyun | `github.com/dobyte/due/log/aliyun/v2` |
| Logging | tencent | `github.com/dobyte/due/log/tencent/v2` |
| Component | http | `github.com/dobyte/due/component/http/v2` |
| Component | mqtt | `github.com/dobyte/due/component/mqtt/v2` |
| Component | pprof (built-in) | `github.com/dobyte/due/v2/component/pprof` |

> Codecs (`encoding/*`), protocol packing (`packet`), the core foundation library (`core/*`), and the utility library (`utils/*`) are all built into the main module and do not need to be imported separately.

### 7. Communication Protocol

In the due framework, the communication protocol uniformly uses the format size+header+route+seq+message:

1. Data packet

```
 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+---------------------------------------------------------------+-+-------------+-------------------------------+-------------------------------+
|                              size                             |h|   extcode   |             route             |              seq              |
+---------------------------------------------------------------+-+-------------+-------------------------------+-------------------------------+
|                                                                message data ...                                                               |
+-----------------------------------------------------------------------------------------------------------------------------------------------+
```

2. Heartbeat packet

```
 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+---------------------------------------------------------------+-+-------------+---------------------------------------------------------------+
|                              size                             |h|   extcode   |                      heartbeat time (ns)                      |
+---------------------------------------------------------------+-+-------------+---------------------------------------------------------------+
```

size: 4 bytes

- Packet length field
- Fixed at 4 bytes and cannot be modified

header: 1 bytes

h: 1 bit

- Heartbeat flag
- %x0 indicates a data packet
- %x1 indicates a heartbeat packet

extcode: 7 bit

- Extended opcode
- The specific opcodes are not yet clearly defined

route: 1 bytes | 2 bytes | 4 bytes

- Message route
- Defaults to 2 bytes; can be changed via the packer's packet.routeBytes setting
- Different routes correspond to different business handling flows
- Heartbeat packets have no message route field
- This parameter is packed by the business packer; both server and client developers need to care about it

seq: 0 bytes | 1 bytes | 2 bytes | 4 bytes

- Message sequence number
- Defaults to 2 bytes; can be changed via the packer's packet.seqBytes setting
- Set packet.seqBytes to 0 to disable the sequence number
- The message sequence number is commonly used to acknowledge request/response message pairs
- Heartbeat packets have no message sequence number field
- This parameter is packed by the business packer packet.Packer; both server and client developers need to care about it

message data: n bytes

- Message data
- Heartbeat packets have no message data
- This parameter is packed by the business packer packet.Packer; both server and client developers need to care about it

heartbeat time: 8 bytes

- Heartbeat data
- Data packets have no heartbeat data
- Uplink heartbeat packets need not carry heartbeat data; downlink heartbeat packets carry 8 bytes of server time (ns) by default, and whether to include the downlink packet time information can be configured in the network library
- This parameter is packed automatically by the network framework layer; server developers do not need to care about it, but client developers do

### 8. Related Toolchain

1. Install the protobuf compiler (use case: developing mesh microservices)

- Linux, using apt or apt-get, for example:

```shell
$ apt install -y protobuf-compiler
$ protoc --version  # Ensure compiler version is 3+
```

- MacOS, using Homebrew:

```shell
$ brew install protobuf
$ protoc --version  # Ensure compiler version is 3+
```

- Windows, download from [Github](https://github.com/protocolbuffers/protobuf/releases):

2. Install the protobuf Go code generator (use case: developing mesh microservices)

```shell
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
```

3. Install the grpc code generator (use case: developing mesh microservices with the [GRPC](https://grpc.io/) component)

```shell
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
```

4. Install the rpcx code generator (use case: developing mesh microservices with the [RPCX](https://rpcx.io/) component)

```shell
go install github.com/rpcxio/protoc-gen-rpcx@latest
```

5. Install the gorm dao code generator (use case: using [GORM](https://gorm.io/) as the database ORM)

```shell
go install github.com/dobyte/gorm-dao-generator@latest
```

6. Install the mongo dao code generator (use case: using [MongoDB](https://github.com/mongodb/mongo-go-driver) as the database ORM)

```shell
go install github.com/dobyte/mongo-dao-generator@latest
```

### 9. Config Center

1. Feature overview

Frequently Asked Questions

What is due?

due is a Game Development library for the Go programming language. Distributed game server framework with a modular component design, providing tcp, kcp, ws and quic gateways

How do I install due?

Install due with the Go module system using `go get dobyte/due`. Check the repository for the current installation instructions.

What category does due belong to?

due is listed under Game Development, specifically Game Development.

← Back to Game Development