我有一个 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
}
在上面的代码片段中,对于来自工作人员(或客户端)的每个请求,服务器端的处理程序都会启动一个计时器和一个 goroutine。 Goroutine 在向客户端发送回复之前恢复处理程序函数所做的更改。
是否有任何方法可以创建“一组计时器”并阻止等待“一组计时器”?此外,每当计时器到期时,阻塞等待就会唤醒并为我们提供计时器句柄。根据计时器类型,我们可以在运行时执行不同的到期处理函数。
我正在尝试在 Go 中实现类似的机制,我们可以在 C++ 中使用 timerfd 和 epoll
来实现。
最佳答案
我建议您探索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 channel 以及从其派生的所有上下文的 Done channel 。
关于go - rpc方法的定时器实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60252784/