go语言心跳超时的实现示例

目录
  • 一、背景
  • 二、心跳超时的实现
    • 2.1 通过select case (设计概念比较多)
    • 2.2 通过time.sleep(简单有效)
  • 三、个人的实现观感

一、背景

本文描述的是客户端接收心跳信息的超时实现。心跳超时,或者接受信息超过限定时间在分布式系统中出现的次数比较多。常见的就有hadoop中节点超时,或者日志中出现timeout的字样。

在学习go语言中,我也根据go语言的机制实现了心跳超时的这个问题。踩过坑,趟过水。

二、心跳超时的实现

2.1 通过select case (设计概念比较多)

这种方法实现心跳,需要对go语言中的channel和select case 机制有所了解。select代码段中没有包含default条件时,会一直阻塞到有通道操作。

需要注意的是!!!! select语言只会阻塞一次,且执行一次。如果需要多次判断,或者可能有多个case条件需要满足,那就需要增加for语句。

首先需要知道的是select是专为channel设计的,所以说每个case表达式都必须是包含操作通道的表达式。下面这段代码是描述了随机抽取一个channel发消息,正常情况下,不会触发超时。为了触发超时,注释掉通道发送数据操作。超时五秒,则触发超时。

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    // 准备好三个通道。
    intChannels := [3]chan int{
        make(chan int, 1),
        make(chan int, 1),
        make(chan int, 1),
    }
    // 随机选择一个通道,并向它发送元素值。
    index := rand.Intn(3)
    fmt.Printf("The index: %d\n", index)

    //️ 取消这行代码的注视,超时条件的选择就会触发。
    //intChannels[index] <- index
    // 哪一个通道中有可取的元素值,哪个对应的分支就会被执行。
    select {
    case <-intChannels[0]:
        fmt.Println("The first candidate case is selected.")
    case <-intChannels[1]:
        fmt.Println("The second candidate case is selected.")
    case elem := <-intChannels[2]:
        fmt.Printf("The third candidate case is selected, the element is %d.\n", elem)
    case <-time.After(5 * time.Second):
        fmt.Println("timed out")
    }
}

2.2 通过time.sleep(简单有效)

通过time.sleep()实现超时操作,是比较巧妙的。一般来说心跳超时是一个双方交互的行为。

下面画一个图来描述一下。

为了方便理解,定义双方都使用共同时间。

下面是代码。

基本的逻辑是:

1、先给客户端设置一个下次超时的时间

2、客户端每次收到心跳的时候,更新这个时间

3、开启一个独立的线程,一致判断当前客户端是否超时。

ps:结合时效和性能,可以间隔一定的时间来进行判断。

package main

import (
    "fmt"
    "sync"
    "time"
)

type Client struct {
    lock sync.Mutex //加锁
    nextTimeOutTime time.Time //下次超时时间
}

const tenSec = 10
/**
刷新每次的心跳超时机制
 */
func (client *Client) freshTimeOutTime()  {
    client.lock.Lock()
    defer client.lock.Unlock()
    client.nextTimeOutTime =time.Now().Add(tenSec*time.Second)
}

//开启一个gp,每隔500ms判断有没有超时
func (client *Client) judgeTimeOut()  {
    for  {
        time.Sleep(500*time.Millisecond)
        fmt.Printf("%v 在判断是否超时\n", client.nextTimeOutTime)
        if time.Now().After(client.nextTimeOutTime) {
            fmt.Printf("%v 超时了\n", client.nextTimeOutTime)
        }
    }
}

//客户端收到以后,修改下次心跳超时时间
func (client *Client) receiveHeart()  {
    client.freshTimeOutTime()
}

//开启一个模拟ping 客户端的线程
func pingClient(client *Client)  {
    for true {
        time.Sleep(11*time.Second)
        fmt.Printf("%v 请求发送时间\n", time.Now())
        client.receiveHeart()
    }

}

func main() {
    client := Client{
        lock:            sync.Mutex{},
        nextTimeOutTime: time.Time{},
    }
    //在当前时刻,更新下次的超时时刻是10s中后
    client.freshTimeOutTime()

    go pingClient(&client)

    go client.judgeTimeOut()

    for true {

    }
}

三、个人的实现观感

使用select case 和 time.sleep实现超时的最大区别在于,time.sleep没有太多的语言相关的语法和知识,更容易理解和掌握。相对于channel来说,掌握需要了解channel的基本使用方法,一些常见的特性等。

到此这篇关于go语言心跳超时的实现示例的文章就介绍到这了,更多相关go语言心跳超时内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • go语言中http超时引发的事故解决

    前言 我们使用的是golang标准库的http client,对于一些http请求,我们在处理的时候,会考虑加上超时时间,防止http请求一直在请求,导致业务长时间阻塞等待. 最近同事写了一个超时的组件,这几天访问量上来了,网络也出现了波动,造成了接口在报错超时的情况下,还是出现了请求结果的成功. 分析下具体的代码实现 type request struct { method string url string value string ps *params } type params stru

  • Go语言如何并发超时处理详解

    实现原理: 并发一个函数,等待1s后向timeout写入数据,在select中如果1s之内有数据向其他channel写入则会顺利执行,如果没有,这是timeout写入了数据,则我们知道超时了. 实现代码: package main import "fmt" import "time" func main() { ch := make(chan int, 1) timeout := make(chan bool, 1) // 并发执行一个函数,等待1s后向timeou

  • Go语言利用time.After实现超时控制的方法详解

    前言 在开始之前,对time.After使用有疑问的朋友们可以看看这篇文章:https://www.jb51.net/article/146063.htm 我们在Golang网络编程中,经常要遇到设置超时的需求,本文就来给大家详细介绍了Go语言利用time.After实现超时控制的相关内容,下面话不多说了,来一起看看详细的介绍吧. 场景: 假设业务中需调用服务接口A,要求超时时间为5秒,那么如何优雅.简洁的实现呢? 我们可以采用select+time.After的方式,十分简单适用的实现. 首先

  • go语言心跳超时的实现示例

    目录 一.背景 二.心跳超时的实现 2.1 通过select case (设计概念比较多) 2.2 通过time.sleep(简单有效) 三.个人的实现观感 一.背景 本文描述的是客户端接收心跳信息的超时实现.心跳超时,或者接受信息超过限定时间在分布式系统中出现的次数比较多.常见的就有hadoop中节点超时,或者日志中出现timeout的字样. 在学习go语言中,我也根据go语言的机制实现了心跳超时的这个问题.踩过坑,趟过水. 二.心跳超时的实现 2.1 通过select case (设计概念比

  • Java语言实现反转链表代码示例

    问题描述 定义一个函数,输入一个链表的头结点,反转该链表并输出反转后的链表的头结点.链表结点如下: public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } 思路1: 要想反转链表,对于结点i,我们要把它的next指向它的前趋,因此我们需要保存前趋结点,同时,如果我们已经把i的next重新赋值,会无法找到i的后继,因此,在重新赋值之前,我们要保存i的后继. 代码:

  • Java语言实现最大堆代码示例

    最大堆 最大堆的特点是父元素比子元素大,并且是一棵完全二叉树. data[1]开始存,data[0]空着不用.也可以把data[0]当成size来用. public class MaxHeap<T extends Comparable<? super T>> { private T[] data; private int size; private int capacity; public MaxHeap(int capacity) { this.data = (T[]) new

  • C语言中的正则表达式使用示例详解

    正则表达式,又称正规表示法.常规表示法(英语:Regular Expression,在代码中常简写为regex.regexp或RE).正则表达式是使用单个字符串来描述.匹配一系列符合某个句法规则的字符串. 在c语言中,用regcomp.regexec.regfree 和regerror处理正则表达式.处理正则表达式分三步: 编译正则表达式,regcomp: 匹配正则表达式,regexec: 释放正则表达式,regfree. 函数原型 /* 函数说明:Regcomp将正则表达式字符串regex编译

  • python 获取键盘输入,同时有超时的功能示例

    如下所示: ''' ###get keyboard input and timeout =5 import sys, time, msvcrt def readInput( caption, default, timeout = 5): start_time = time.time() sys.stdout.write('%s(%s):'%(caption, default)); input = '' while True: if msvcrt.kbhit(): chr = msvcrt.get

  • VSCode各语言运行环境配置方法示例详解

    系统环境变量的配置 如:将F:\mingw64\bin添加到系统环境变量Path中 VSCode软件语言json配置C语言 创建个.vscode文件夹,文件夹内创建以下两个文件 launch.json 文件配置 { "version": "0.2.0", "configurations": [ { "name": "(gdb) Launch", "type": "cppdbg&

  • c语言左移和右移的示例详解

    逻辑移位,简单理解就是物理上按位进行的左右移动,两头用0进行补充,不关心数值的符号问题. 算术移位,同样也是物理上按位进行的左右移动,两头用0进行补充,但必须确保符号位不改变. 算术移位指令 算术移位指令有:算术左移SAL(ShiftAlgebraic Left)和算术右移SAR(ShiftAlgebraic Right).算术移位指令的功能描述如下: (1)算术左移SAL把目的操作数的低位向高位移,空出的低位补0: (2)算术右移SAR把目的操作数的高位向低位移,空出的高位用最高位(符号位)填

  • 关于C语言位运算的简单示例

    位运算是指按二进制进行的运算.在系统软件中,常常需要处理二进制位的问题.C语言提供了6个位操作运算符.这些运算符只能用于整型操作数,即只能用于带符号或无符号的char,short,int与long类型. 1.输入一个float型数,以十六进制形式输出其32位机器数. #include<stdio.h> void main() { float a; int *p; printf("Input a float number:\n"); scanf("%f",

  • c# socket心跳超时检测的思路(适用于超大量TCP连接情况下)

    假设一种情景: TCP服务器有1万个客户端连接,如果客户端5秒钟不发数据,则要断开.服务端如何检测客户端是否超时?这看起来是一个非常简单的问题,其实不然! 最简单的处理方法是: 启动一个线程,每隔一段时间,检查每个连接是否超时.每次处理需要1万次检查.计算量太大!检查的时间间隔不能太小,否则大大增加计算量:如果间隔时间太大,超时误差会增大. 本文提出一种新颖的处理方法,就是针对这个看似简单而不易解决的问题!(以下用socket表示一个客户端连接) 1 内存布局图 假设socket3有新的数据到达

  • R语言时间序列TAR阈值自回归模型示例详解

    为了方便起见,这些模型通常简称为TAR模型.这些模型捕获了线性时间序列模型无法捕获的行为,例如周期,幅度相关的频率和跳跃现象.Tong和Lim(1980)使用阈值模型表明,该模型能够发现黑子数据出现的不对称周期性行为. 一阶TAR模型的示例: σ是噪声标准偏差,Yt-1是阈值变量,r是阈值参数, {et}是具有零均值和单位方差的iid随机变量序列. 每个线性子模型都称为一个机制.上面是两个机制的模型. 考虑以下简单的一阶TAR模型: #低机制参数 i1 = 0.3 p1 = 0.5 s1 = 1

随机推荐