DEV Community

Jones Charles
Jones Charles

Posted on

Keep Your TCP Connections Alive & Healthy with GoFrame's gtimer

Hey there, fellow developers! πŸ‘‹ Today, we're diving into a practical solution for a common challenge in network programming - implementing TCP heartbeats. We'll be using Go and the awesome GoFrame framework to create a clean and efficient implementation.

The Challenge: Why Do We Need Heartbeats? πŸ€”

Ever had your TCP connection mysteriously drop in production? You're not alone! Long-running TCP connections can break for various reasons:

  • 🌐 Network hiccups and instability
  • 🧱 Firewall timeouts or NAT issues
  • πŸ’₯ Unexpected program crashes
  • πŸ”Œ Manual connection closures

Without proper heartbeat mechanisms, these issues can lead to silent failures, data loss, and frustrated users. Let's fix that!

Enter gtimer: Your New Best Friend 🀝

GoFrame's gtimer is a super handy timing task manager that makes implementing heartbeats a breeze. It offers three main types of tasks:

πŸ“Œ One-time tasks (AddOnce)
πŸ”„ Loop tasks with count (AddTimes)
♾️ Permanent tasks (Add)
Enter fullscreen mode Exit fullscreen mode

For our heartbeat implementation, we'll use the Add method to create a permanent task that keeps our connections healthy.

Show Me the Code! πŸ’»

Let's build this thing! We'll implement both server and client sides.

Server-Side Magic ⚑

Here's how we handle heartbeats on the server:

func (s *Server) handleConnection(conn gnet.Conn) {
    // Respond to heartbeats before timeout
    gtimer.Add(s.HeartbeatInterval, func() {
       j := gjson.New(g.Map{"pong": 11})
       err := conn.AsyncWrite(j.MustToJson())
       if err != nil {
          return
       }
    })
}
Enter fullscreen mode Exit fullscreen mode

Client-Side Goodness 🌟

And here's our client implementation:

func (c *Client) startHeartbeat() {
    // Send heartbeats at regular intervals
    gtimer.Add(c.HeartbeatTimer, func() {
       j := gjson.New(g.Map{"ping": 10})
       if err := c.Conn.AsyncWrite(j.MustToJson()); err != nil {
          err = c.Conn.Close()
          if err != nil {
             return
          }
          gtimer.Exit()
       }
    })
}
Enter fullscreen mode Exit fullscreen mode

Pro Tips for Production Use πŸ†

After implementing this in several projects, here are some battle-tested tips:

  1. Tune Your Intervals: Start with a 30-second heartbeat interval and adjust based on your needs. Too frequent = unnecessary overhead, too infrequent = delayed failure detection.

  2. Implement Retry Logic: Don't give up after one failed heartbeat! Add a retry mechanism:

func (c *Client) handleHeartbeatFailure() {
    retries := 3
    for i := 0; i < retries; i++ {
        if c.sendHeartbeat() == nil {
            return // Success!
        }
        time.Sleep(time.Second) // Wait before retry
    }
    // Handle permanent failure
}
Enter fullscreen mode Exit fullscreen mode
  1. Monitor & Log: Add logging to track connection health:
if err := c.sendHeartbeat(); err != nil {
    log.Printf("❌ Heartbeat failed: %v", err)
    // Handle failure
}
Enter fullscreen mode Exit fullscreen mode

Why This Approach Rocks 🎸

  • 🎯 Clean, readable code
  • ⚑ Non-blocking with async writes
  • πŸ›‘οΈ Built-in error handling
  • πŸ”§ Easy to customize

Let's Make It Better Together! πŸ’ͺ

This is just one way to implement TCP heartbeats - I'd love to hear your approaches! Have you encountered any specific challenges with TCP connections? How do you handle them? Drop your thoughts in the comments below!

Resources to Learn More πŸ“š

Happy coding! πŸš€


If you found this helpful, don't forget to like and share! Follow me for more Go programming tips and tutorials!

Playwright CLI Flags Tutorial

5 Playwright CLI Flags That Will Transform Your Testing Workflow

  • 0:56 --last-failed: Zero in on just the tests that failed in your previous run
  • 2:34 --only-changed: Test only the spec files you've modified in git
  • 4:27 --repeat-each: Run tests multiple times to catch flaky behavior before it reaches production
  • 5:15 --forbid-only: Prevent accidental test.only commits from breaking your CI pipeline
  • 5:51 --ui --headed --workers 1: Debug visually with browser windows and sequential test execution

Learn how these powerful command-line options can save you time, strengthen your test suite, and streamline your Playwright testing experience. Click on any timestamp above to jump directly to that section in the tutorial!

Watch Full Video πŸ“ΉοΈ

Top comments (0)

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

πŸ‘‹ Kindness is contagious

If this article connected with you, consider tapping ❀️ or leaving a brief comment to share your thoughts!

Okay