DEV Community

Cover image for 4.Zinx Global Configuration
Aceld
Aceld

Posted on • Edited on

4.Zinx Global Configuration

[Zinx]

<1.Building Basic Services with Zinx Framework>
<2. Zinx-V0.2 Simple Connection Encapsulation and Binding with Business>
<3.Design and Implementation of the Zinx Framework's Routing Module>
<4.Zinx Global Configuration>
<5.Zinx Message Encapsulation Module Design and Implementation>
<6.Design and Implementation of Zinx Multi-Router Mode>
<7. Building Zinx's Read-Write Separation Model>
<8.Zinx Message Queue and Task Worker Pool Design and Implementation>
<9. Zinx Connection Management and Property Setting>

[Zinx Application - MMO Game Case Study]

<10. Application Case Study using the Zinx Framework>
<11. MMO Online Game AOI Algorithm>
<12.Data Transmission Protocol: Protocol Buffers>
<13. MMO Game Server Application Protocol>
<14. Building the Project and User Login>
<15. World Chat System Implementation>
<16. Online Location Information Synchronization>
<17. Moving position and non-crossing grid AOI broadcasting>
<18. Player Logout>
<19. Movement and AOI Broadcast Across Grids>


source code

https://github.com/aceld/zinx/blob/master/examples/zinx_release/zinx-v0.4.tar.gz


As the framework grows, the number of parameters increases. To avoid the hassle of frequently modifying parameters later, Zinx needs a module to load configurations and an object to globally access Zinx parameters.

4.1 Implementation of Global Configuration in Zinx-V0.4

First, let's design a simple configuration loading module. We'll choose the widely used JSON format for the configuration file. The configuration information is as follows:

zinx.json

{
    "Name": "demo server",
    "Host": "127.0.0.1",
    "TcpPort": 7777,
    "MaxConn": 3
}
Enter fullscreen mode Exit fullscreen mode

Now, Zinx needs to create an object to store global configuration information.

1. Create the Global Parameters File

Create a folder named utils in the zinx directory. The utils folder will mainly contain shared utility modules of the Zinx framework. Inside the utils folder, create a file named globalobj.go. Initially, write the code as follows:

zinx/utils/globalobj.go

package utils

import (
    "encoding/json"
    "io/ioutil"
    "zinx/ziface"
)

/*
    Stores all global parameters related to the Zinx framework for use by other modules.
    Some parameters can also be configured by users in zinx.json.
*/
type GlobalObj struct {
    TcpServer ziface.IServer // Current global Server object of Zinx
    Host string // Current server host IP
    TcpPort int // Current server host listening port
    Name string // Current server name
    Version string // Current Zinx version
    MaxPacketSize uint32 // Maximum size of data packet to be read
    MaxConn       int    // Maximum number of allowed connections on the current server host
}

/*
    Define a global object
*/
var GlobalObject *GlobalObj

Enter fullscreen mode Exit fullscreen mode

The above code defines a GlobalObject object globally, and the variable is capitalized to be exposed to other modules. This allows other modules to access the parameters inside it.

The global configuration includes the following parameters:

  • TcpServer: This is an IServer type attribute, representing the current running Server object of Zinx. This attribute cannot be configured through zinx.json. It is added to the global object after the Server instance is started, allowing other modules to access the current Server instance of Zinx.
  • Host: The IP address on which the Zinx service listens. It is a string type and can be configured in the zinx.json configuration file.
  • TcpPort: The port number on which the Zinx service listens. It is an integer type and can be configured in the zinx.json configuration file.
  • Name: The name of the current Zinx service, which has the same meaning as the Name attribute in the Server.
  • Version: The version number of the current Zinx, used for management and differentiation in logs.
  • MaxPacketSize: Currently, Zinx does not utilize this capability. It represents the maximum length of the data packet that the Zinx service reads from the remote end.
  • MaxConn: Currently, Zinx does not utilize this capability. It represents the maximum number of connections allowed on the current server. It will be used in future versions to limit the number of Zinx connections.

2. Providing the init() Initialization Method

Next, we'll provide an init() method for globalobj.go to initialize the GlobalObject object and load the server application configuration file conf/zinx.json. The code implementation is as follows:

// zinx/utils/globalobj.go

// Read the user's configuration file
func (g *GlobalObj) Reload() {
    data, err := ioutil.ReadFile("conf/zinx.json")
    if err != nil {
        panic(err)
    }
// Parse the JSON data into the struct
// fmt.Printf("json: %s\n", data)
err = json.Unmarshal(data, &GlobalObject)
    if err != nil {
        panic(err)
    }
}

/*
    Provide the init() method, which is automatically loaded.
*/
func init() {
    // Initialize the GlobalObject variable and set some default values
    GlobalObject = &GlobalObj{
        Name: "ZinxServerApp",
        Version: "V0.4",
        TcpPort: 7777,
        Host: "0.0.0.0",
        MaxConn: 12000,
        MaxPacketSize: 4096,
    }

    // Load some user-configurable parameters from the configuration file
    GlobalObject.Reload()
}
Enter fullscreen mode Exit fullscreen mode

When each module is loaded, the init() method of that module is executed. In the init() method, the Reload() method is called to load the local configuration file zinx.json and load the configurable parameters into the Zinx memory.

Note: The translation assumes that the path "conf/zinx.json" refers to the configuration file zinx.json located in the "conf" directory relative to the current module file.

3. Replacing Hard-coded Parameters and Server Initialization Parameter Configuration

Next, we will replace the configurable parameters from the global configuration into the existing implementation logic of Zinx.

First, when creating a new Server using the NewServer() function, we will assign the Server properties using GlobalObject:

// zinx/znet/server.go
/*
   Create a server instance
*/
func NewServer() ziface.IServer {
    // Initialize the global configuration file first
    utils.GlobalObject.Reload()

    s := &Server{
        Name:      utils.GlobalObject.Name,        // Get from global parameters
        IPVersion: "tcp4",
        IP:        utils.GlobalObject.Host,        // Get from global parameters
        Port:      utils.GlobalObject.TcpPort,     // Get from global parameters
        Router:    nil,
    }
    return s
}
Enter fullscreen mode Exit fullscreen mode

To verify that the parameters have been successfully loaded, we'll add some debug information in the Server.Start() method:

// zinx/znet/server.go

// Start the network service
func (s *Server) Start() {
    fmt.Printf("[START] Server name: %s, listener at IP: %s, Port %d is starting\n", s.Name, s.IP, s.Port)
    fmt.Printf("[Zinx] Version: %s, MaxConn: %d, MaxPacketSize: %d\n",
        utils.GlobalObject.Version,
        utils.GlobalObject.MaxConn,
        utils.GlobalObject.MaxPacketSize)

    // ...
    // ...
}
Enter fullscreen mode Exit fullscreen mode

Of course, there are other fixed hard-coded parameters that can be configured in the configuration file and replaced with global parameters. We won't list them here.

The current directory structure of the Zinx framework looks like this:

├── README.md
├── utils
   └── globalobj.go
├── ziface
   ├── iconnnection.go
   ├── irequest.go
   ├── irouter.go
   └── iserver.go
└── znet
    ├── connection.go
    ├── request.go
    ├── router.go
    ├── server.go
    └── server_test.go
Enter fullscreen mode Exit fullscreen mode

4.2 Completing the Application with Zinx-V0.4

Now, in order to complete the server based on Zinx, we need to prepare a configuration file conf/zinx.json. The project code path for the Zinx application is as follows:

├── Client.go
├── conf
│   └── zinx.json
└── Server.go
Enter fullscreen mode Exit fullscreen mode

Now, let's modify Server.go by removing unnecessary PreHandle() and PostHandle() methods, and keeping only the Handle() method for business logic. The code is as follows:

// Server.go
package main

import (
    "fmt"
    "zinx/ziface"
    "zinx/znet"
)

// Custom router for ping test
type PingRouter struct {
    znet.BaseRouter
}

// Test Handle
func (this *PingRouter) Handle(request ziface.IRequest) {
    fmt.Println("Call PingRouter Handle")
    _, err := request.GetConnection().GetTCPConnection().Write([]byte("ping...ping...ping\n"))
    if err != nil {
        fmt.Println("Callback ping ping ping error")
    }
}

func main() {
    // Create a server instance
    s := znet.NewServer()

    // Configure the router
    s.AddRouter(&PingRouter{})

    // Start the server
    s.Serve()
}
Enter fullscreen mode Exit fullscreen mode

To start the server-side program Server.go, use the following command:

$ go run Server.go
Enter fullscreen mode Exit fullscreen mode

The expected output is as follows:

$ go run Server.go 
Add Router success! 
[START] Server name: demo server, listener at IP: 127.0.0.1, Port 7777 is starting
[Zinx] Version: V0.4, MaxConn: 3, MaxPacketSize: 4096
start Zinx server demo server success, now listening...
Enter fullscreen mode Exit fullscreen mode

4.3 Conclusion

Now, the configurable parameters can be passed through the developer's configuration file. Readers can optimize the implementation logic of this configuration file or use other configuration file protocols as well. The purpose of the configuration file is to allow developers to debug or deploy the program without recompiling, by changing some necessary parameters to switch service capabilities or functionality. Generally, a backend daemon service-type application should have the capability to use a configuration file.


source code

https://github.com/aceld/zinx/blob/master/examples/zinx_release/zinx-v0.4.tar.gz


[Zinx]

<1.Building Basic Services with Zinx Framework>
<2. Zinx-V0.2 Simple Connection Encapsulation and Binding with Business>
<3.Design and Implementation of the Zinx Framework's Routing Module>
<4.Zinx Global Configuration>
<5.Zinx Message Encapsulation Module Design and Implementation>
<6.Design and Implementation of Zinx Multi-Router Mode>
<7. Building Zinx's Read-Write Separation Model>
<8.Zinx Message Queue and Task Worker Pool Design and Implementation>
<9. Zinx Connection Management and Property Setting>

[Zinx Application - MMO Game Case Study]

<10. Application Case Study using the Zinx Framework>
<11. MMO Online Game AOI Algorithm>
<12.Data Transmission Protocol: Protocol Buffers>
<13. MMO Game Server Application Protocol>
<14. Building the Project and User Login>
<15. World Chat System Implementation>
<16. Online Location Information Synchronization>
<17. Moving position and non-crossing grid AOI broadcasting>
<18. Player Logout>
<19. Movement and AOI Broadcast Across Grids>


Author:
discord: https://discord.gg/xQ8Xxfyfcz
zinx: https://github.com/aceld/zinx
github: https://github.com/aceld
aceld's home: https://yuque.com/aceld

Top comments (0)