【问题标题】:Go - The most optimal way to implement a timeoutGo - 实现超时的最佳方式
【发布时间】:2021-12-23 12:34:50
【问题描述】:

我有一个异步部署的服务,我需要等待指定的时间才能使其上线。如果指定的时间过去了,我们仍然无法找到服务,那么我们就会出错。在 go 中写这个的最佳方式是什么?我正在考虑使用context.WithTimeout,但不确定它到底是如何工作的。感谢您的帮助!

func (c *Client) WaitForServiceToComeAlive(ctx context.Context, name string, timeout time.Duration) error {
    
    var mysvc *Service
    var err error

    endtime := time.Now().Add(timeout)

    for time.Now().Before(endtime) {
        mysvc, err = c.GetService(ctx, name)
        if err != nil {
            return err
        }

        if mysvc != nil {
            break
        }

        time.Sleep(time.Second * 10)
    }

    if mysvc == nil {
        return fmt.Errorf("svc %s did not register", name)
    }

    return nil
}

【问题讨论】:

    标签: go asynchronous timeout polling


    【解决方案1】:

    永远不要使用time.Sleep,尤其是在长时间使用的情况下 - 因为它是不间断的。为什么这很重要?如果它在一个 goroutine 中并且该任务不会完成(即上下文被取消),那么您宁愿立即中止。

    所以要创建一个带有取消的轮询等待:

    select {
    case <-ctx.Done():               // cancel early if context is canceled
        return ctx.Err()
    case <-time.After(pollInterval): // wait for pollInterval duration
    }
    

    将较大的超时设置在输入上下文中:

    ctx := context.TODO() // <- outer request context goes here or context.Background()
    
    // wrap context with a timeout
    ctx, cancel := context.WithTimeout(ctx, 1 * time.Minute)
    defer cancel() // avoid leaks
    
    err := c.WaitForServiceToComeAlive(ctx, "job", 10*time.Second /* poll interval */)
    

    然后您的服务等待函数简化为:

    func (c *Client) WaitForServiceToComeAlive(ctx context.Context, name string, pollInterval time.Duration) error {
    
        var mysvc *Service
        var err error
    
        for {
            mysvc, err = c.GetService(name) // <- this should take a ctx too - if possible for early cancelation
            if err != nil {
                return err
            }
            if mysvc != nil {
                return nil
            }
    
            select {
            case <-ctx.Done():
                return ctx.Err()
            case <-time.After(pollInterval):
            }
        }
    
    }
    

    https://play.golang.org/p/JwH5CMyY0I2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-05
      • 2016-06-14
      • 1970-01-01
      • 2022-12-10
      • 2018-03-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多