Skip to content

05 Zinx HeartBeat

刘丹冰 edited this page May 12, 2023 · 5 revisions

Case Source Code : https://github.com/aceld/zinx-usage/tree/main/zinx_heartbeat

1. HeartBeat Mechanism

Zinx provides a heart beat mechanism, which is bi-directional. Both the server and the client can send heart beat messages to each other. The overall process of Zinx's heart beat mechanism is as follows:

image

The process of heartbeat detection as part of the above mechanism is as follows:

image

The parameters involved in the heartbeat detection process, such as interval, HeartBeatMax, MakeMsg (to make heartbeat messages), OnRemoteNotAlive (the callback logic for remote heartbeat timeout), HeartBeatMsgID (the message ID for heartbeat messages), and Router (the logic to handle heartbeat messages), can all be configured by developers. If developers have no customized requirements, Zinx also provides some default parameters for developers to use directly.

2 Default parameter to start HeartBeat detection

2.1 Default parameters

Parameter Default Value
HeartBeatMsgID 99999(integer)
interval (detection interval / heartbeat message sending interval) passed to StartHeartBeat method as 3 seconds
HeartBeatMax (maximum heartbeat timeout) 10s
OnRemoteNotAlive (callback logic for remote heartbeat timeout) image
func notAliveDefaultFunc(conn ziface.IConnection) image

|

2.2 Start Heartbeat Detection with Default Parameters on Server Side

package main

import (
	"github.com/aceld/zinx/znet"
	"time"
)

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

	// Start heartbeat detection with default parameters (check every 3 seconds)
	s.StartHeartBeat(3 * time.Second)

	// Start the server
	s.Serve()
}

2.3 Starting default Heartbeat detection for client

package main

import (
	"github.com/aceld/zinx/znet"
	"time"
)

func main() {
	// Creating a client instance
	client := znet.NewClient("127.0.0.1", 8999)

	// Starting Heartbeat detection, checking every 3 seconds by default
	client.StartHeartBeat(3 * time.Second)

	// Starting the client
	client.Start()

	// Waiting for an interrupt signal to prevent the process from exiting
	select {}
}

3. Customizing Heartbeat Messages and Processing Mechanisms

Zinx's heartbeat detection mechanism also provides the following options, which can be passed as custom parameters when creating a heartbeat detector using the method StartHeartBeatWithOption(interval time.Duration, option *ziface.HeartBeatOption):

// User-defined heartbeat message processing function
type HeartBeatMsgFunc func(IConnection) []byte

// User-defined processing function when the remote connection is not alive
type OnRemoteNotAlive func(IConnection)

type HeartBeatOption struct {
	MakeMsg          HeartBeatMsgFunc // User-defined heartbeat message processing function
	OnRemoteNotAlive OnRemoteNotAlive // User-defined processing function when the remote connection is not alive
	HeadBeatMsgID    uint32           // User-defined heartbeat detection message ID
	Router           IRouter          // User-defined heartbeat detection message business processing route
}

3.1 Starting custom heartbeat detection on the server

package main

import (
	"fmt"
	"github.com/aceld/zinx/ziface"
	"github.com/aceld/zinx/znet"
	"time"
)

// Custom heartbeat message processing method
func myHeartBeatMsg(conn ziface.IConnection) []byte {
	return []byte("heartbeat, I am server, I am alive")
}

// Custom method to handle remote connection not alive
func myOnRemoteNotAlive(conn ziface.IConnection) {
	fmt.Println("myOnRemoteNotAlive is Called, connID=", conn.GetConnID(), "remoteAddr = ", conn.RemoteAddr())
	// Close the connection
	conn.Stop()
}

// Custom router for heartbeat messages
type myHeartBeatRouter struct {
	znet.BaseRouter
}

func (r *myHeartBeatRouter) Handle(request ziface.IRequest) {
	// Business logic handling
	fmt.Println("in MyHeartBeatRouter Handle, recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData()))
}

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

	myHeartBeatMsgID := 88888

	// Start heartbeat detection with custom options
	s.StartHeartBeatWithOption(1*time.Second, &ziface.HeartBeatOption{
		MakeMsg:          myHeartBeatMsg,
		OnRemoteNotAlive: myOnRemoteNotAlive,
		Router:           &myHeartBeatRouter{},
		HeadBeatMsgID:    uint32(myHeartBeatMsgID),
	})

	// Start the server
	s.Serve()
}

3.2 Enable Custom Heartbeat Check on the Client Side

package main

import (
	"fmt"
	"github.com/aceld/zinx/ziface"
	"github.com/aceld/zinx/znet"
	"time"
)

// Custom heartbeat message processing function for the client
func myClientHeartBeatMsg(conn ziface.IConnection) []byte {
	return []byte("heartbeat, I am Client, I am alive")
}

// Custom processing function when the remote connection is not alive
func myClientOnRemoteNotAlive(conn ziface.IConnection) {
	fmt.Println("myClientOnRemoteNotAlive is Called, connID=", conn.GetConnID(), "remoteAddr = ", conn.RemoteAddr())
	// Close the connection
	conn.Stop()
}

// Custom heartbeat message processing method for the client
type myClientHeartBeatRouter struct {
	znet.BaseRouter
}

func (r *myClientHeartBeatRouter) Handle(request ziface.IRequest) {
	// Business logic processing
	fmt.Println("in myClientHeartBeatRouter Handle, recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData()))
}

func main() {
	// Create a client handle using the Zinx API
	client := znet.NewClient("127.0.0.1", 8999)

	myHeartBeatMsgID := 88888

	// Start heartbeat check
	client.StartHeartBeatWithOption(3*time.Second, &ziface.HeartBeatOption{
		MakeMsg:          myClientHeartBeatMsg,
		OnRemoteNotAlive: myClientOnRemoteNotAlive,
		Router:           &myClientHeartBeatRouter{},
		HeadBeatMsgID:    uint32(myHeartBeatMsgID),
	})

	// Start the client
	client.Start()

	select {}
}

3.3 Setting HeartBeatMax for Maximum Timeout

It can be set through the zinx.json configuration file or passed through the Option when creating a Server.

conf/zinx.json

{
  "Name":"Zinx Heartbeat",
  "Host":"127.0.0.1",
  "TcpPort":8999,
  "MaxConn":3,
  "WorkerPoolSize":10,
  "LogDebugClose": true,
  "HeartbeatMax": 10
}

Alternatively, the HeartBeatMax parameter can be passed through the creation of the Server:

func main() {
	s := znet.NewUserConfServer(&zconf.Config{
		HeartbeatMax: 20, // Set the maximum timeout interval (in seconds)
	})

	myHeartBeatMsgID := 88888

	// Start heartbeating
	s.StartHeartBeatWithOption(1*time.Second, &ziface.HeartBeatOption{
		MakeMsg:          myHeartBeatMsg,
		OnRemoteNotAlive: myOnRemoteNotAlive,
		Router:           &myHeartBeatRouter{},
		HeadBeatMsgID:    uint32(myHeartBeatMsgID),
	})

	s.Serve()
}