rpc 方法的定时器实现

Posted

技术标签:

【中文标题】rpc 方法的定时器实现【英文标题】:Timer implementation for rpc method 【发布时间】:2020-02-16 20:13:22 【问题描述】:

我有一个服务于客户端请求的 Go RPC 服务器。客户端向服务器请求工作(或任务),服务器将任务分配给客户端。服务器期望工作人员(或客户端)在时间限制内完成任何任务。所以服务端需要一个超时事件回调机制。

这是我目前尝试过的。

func (l *Listener) RequestHandler(request string, reply string) error 
    // some other work
    // ....
    _timer := time.NewTimer(time.Second * 5) // timer for 2 seconds
    go func() 
        // simulates a client not replying case, with timeout of 2 sec
        y := <-_timer.C
        fmt.Println("TimeOut for client")
        // revert state changes becasue of client fail
    ()

    // set reply
    // update some states
    return nil

在上面的 sn-p 中,对于来自工作人员(或客户端)的每个请求,服务器端的处理程序都会启动一个计时器和一个 goroutine。 goroutine 在向客户端发送回复之前还原处理函数所做的更改。

有什么方法可以创建“一组定时器”并阻止等待“一组定时器”?此外,每当计时器到期时,阻塞等待就会唤醒并为我们提供计时器句柄。根据计时器类型,我们可以在运行时执行不同的到期处理函数。

我正在尝试在 Go 中实现类似的机制,我们可以在 C++ 中使用 timerfd with epoll 实现。

Go 中计时器示例实现的完整代码。 server.go 和 client.go。

【问题讨论】:

为什么需要“一组定时器”? @BurakSerdar 假设一个 RPC 方法需要与其他几个进程通信,并且每个通信都需要一个计时器, 通常,服务器端的每个请求都在自己的 goroutine 中运行。你可能想多了你的问题。对于超时,请使用带超时的上下文。 【参考方案1】:

我建议你探索一下 context

可以这样做:

func main() 
    c := context.Background()
    wg := &sync.WaitGroup
    f(c, wg)
    wg.Wait()


func f(c context.Context, wg *sync.WaitGroup) 
    c, _ = context.WithTimeout(c, 3*time.Second)
    wg.Add(1)

    go func(c context.Context) 
        defer wg.Done()
        select 
        case <-c.Done():
            fmt.Println("f() Done:", c.Err())
            return
        case r := <-time.After(5 * time.Second):
            fmt.Println("f():", r)
        
    (c)

基本上你启动一个基本上下文,然后从中派生其他上下文,当一个上下文终止时,无论是通过传递时间还是调用它的close,它都会关闭它的Done 通道和从它派生的所有上下文的 Done 通道。

【讨论】:

以上是关于rpc 方法的定时器实现的主要内容,如果未能解决你的问题,请参考以下文章

java实现定时任务的三种方法

linux定时器的实现方法

Python:定时在单独的线程中调用的函数

java定时器 限制方法调用次数

python下timer定时器常用的两种实现方法

Java 如何实现这样的定时任务