Maison  >  Article  >  développement back-end  >  Les goroutines appelées récursivement par time.AfterFunc() sont mal conçues

Les goroutines appelées récursivement par time.AfterFunc() sont mal conçues

WBOY
WBOYavant
2024-02-09 13:48:21817parcourir

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

L'éditeur PHP Xigua estime que la phrase "La conception de goroutine appelée récursivement par time.AfterFunc() est très mauvaise" reflète une idée de conception déraisonnable. En programmation simultanée, l'appel récursif de goroutines peut entraîner une consommation excessive de ressources, et même provoquer des problèmes tels qu'un blocage et un débordement de mémoire. Par conséquent, les appels récursifs doivent être utilisés avec prudence et d'autres alternatives pour résoudre le problème doivent être envisagées afin de garantir les performances et la stabilité du programme. Lors de l’écriture du code, nous devons toujours prêter attention à la rationalité de la conception pour éviter des problèmes inutiles.

Contenu de la question

J'ai une petite application http (A). Au démarrage, il appelle un autre service http (B) pour vérifier la licence et si la licence est OK, le serveur http (A) démarre. Si la vérification échoue, une erreur fatale se produira et se terminera

Les contrôles de licence sont effectués toutes les 24 heures

Créer récursivement une nouvelle goroutine toutes les 24 heures serait-il considéré comme une mauvaise conception ? Vérifiez mon code ci-dessous. La goroutine précédente sera-t-elle fermée ou continuera-t-elle à s'exécuter, puis n goroutines s'appelleront et se termineront ?

Chaque nouvelle goroutine est-elle appelée depuis la goroutine principale ou depuis la goroutine enfant ?

Module de vérification de licence. Un service d'inspection 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)
}

Dans le package principal avant le démarrage du serveur HTTP (A)

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

Solution

Peut-être pouvez-vous repenser la conception du problème. Par exemple :

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
}

Fondamentalement, il crée une goroutine qui vérifie périodiquement et informe le contexte ou le canal si quelque chose ne va pas.

Si je comprends bien la question, il vous suffit de rester simple. Un élément de base consiste à réessayer une demande si elle échoue. Sinon, il y a une nouvelle tentative de 24 heures. La dernière couche consiste à réagir à la vérification si elle échoue. Vous pouvez utiliser le contexte, le canal ou tout ce que vous aimez vraiment

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer