首頁  >  文章  >  後端開發  >  由 time.AfterFunc() 遞歸呼叫的 goroutine 的設計很糟糕

由 time.AfterFunc() 遞歸呼叫的 goroutine 的設計很糟糕

WBOY
WBOY轉載
2024-02-09 13:48:21817瀏覽

由 time.AfterFunc() 递归调用的 goroutine 的设计很糟糕

php小編西瓜認為,"由 time.AfterFunc() 遞歸調用的 goroutine 的設計很糟糕"這句話反映了一種不合理的設計思路。在並發程式設計中,遞歸呼叫的 goroutine 可能導致資源消耗過大,甚至引發死鎖和記憶體溢位等問題。因此,應該謹慎使用遞歸調用,並考慮使用其他替代方案來解決問題,以確保程式的效能和穩定性。在編寫程式碼時,我們應該時時注意設計的合理性,避免出現不必要的問題。

問題內容

我有一個小型 http 應用程式 (A)。在啟動時,它會呼叫另一個 http 服務 (B) 來驗證許可證,如果許可證正常,則 http 伺服器 (A) 啟動。如果驗證失敗A則出現致命錯誤退出

許可證檢查每 24 小時進行一次

每 24 小時遞歸創建一個新的 goroutine 會被認為是一個糟糕的設計嗎?檢查下面我的程式碼。之前的goroutine會關閉還是繼續運行然後n個goroutine互相調用而結束

每個新的 goroutine 是從主 goroutine 調用還是從子 goroutine 調用?

許可證驗證模組。 A 檢查服務 B

func Request(retry bool) error {
    // request and verify license (external http service)
    err := verify_license()
    if err != nil {
        return err
    }
    
    if retry {
        //  Renew verification timeout (renew license every 24 hours)
        time.AfterFunc(LICENSE_TIMEOUT, func(){
            request_retry()
        })
    }
    
    return nil
}

func request_retry(){
    for i := 0; i < LICENSE_RETRY; i++ {
        if err := v.Request(false); err == nil {
            break
        }
        
        time.Sleep(LICENSE_RETRY_TIMEOUT)
    }
    
    time.Sleep(LICENSE_TIMEOUT)
    v.Request(true)
}

在HTTP伺服器(A)啟動之前的主套件中

if err := license_verify.Request(true); err != nil {
    log.Fatal(err.Error())
}

解決方法

也許你可以重新思考問題的設計。例如:

func main() {
    if !checkLicense() {
        log.Fatal("license check failed")
    }

    srv := http.Server{} // 
    
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()
    go func() {
         for {
             select {
             case <-ctx.Done(): // in case you want to instal signal handlers etc
                  return
             case <-time.After(24 * time.Hour):
                  if !checkLicense() {
                      cancel() // or srv.Shtdown, really depends on you
                  }
             }
         }
    }()

    if err := srv.ListenAndServe(); err != nil {
        log.Fatal(err)
    }
}

func checkLicense() bool {
    // add retries per request here
}

基本上,它的作用是創建一個 goroutine,定期檢查並在出現問題時通知上下文或通道。

如果我正確理解了這個問題,那麼你只需要保持簡單。一個建置區塊是請求失敗時重試。除此之外,是 24 小時重試。最後一層是,如果檢查失敗,則對其做出反應。您可以使用上下文、頻道或您真正喜歡的任何內容

以上是由 time.AfterFunc() 遞歸呼叫的 goroutine 的設計很糟糕的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除