Dacă un http.Client este deja partajat de cereri concurente, păstrați câmpul său Transport stabil. Un înveliș poate sincroniza ce transport complet configurat primește fiecare tură ulterioară:

type routeSlot struct {
    mu sync.RWMutex
    current http.RoundTripper
}

func (s *routeSlot) RoundTrip(r *http.Request) (*http.Response, error) {
    s.mu.RLock()
    current := s.current
    s.mu.RUnlock()
    return current.RoundTrip(r)
}

func (s *routeSlot) Set(next http.RoundTripper) {
    s.mu.Lock()
    s.current = next
    s.mu.Unlock()
}

Cu net/http și sync, inițializați-l înainte de a publica clientul:

slot := &routeSlot{current: initialTransport}
client := &http.Client{Transport: slot}

slot.Set(nextTransport)

initialTransport și nextTransport trebuie să fie non-nil, complet configurate și sigure din punctul de vedere al concurenței. Construiți fiecare transport proxy înainte de a-l publica și lăsați configurația neschimbată cât timp cererile îl folosesc.

Blocajul protejează doar instantaneul pointerului, așa că o cerere lentă nu ține blocajul de rutare pe toată durata schimbului său de rețea. O cerere care folosește deja instantaneul anterior continuă pe acel transport; comutarea nu o reia și nu îi mută conexiunea.

Păstrați și retrageți transporturile vechi prin ciclul de viață limitat al aplicației, lăsând lucrul în curs să se termine și închizând pool-urile inactive când este potrivit. O redirecționare poate provoca un alt RoundTrip după o comutare. Dacă un întreg flux de lucru necesită o singură rută, atribuiți-o la granița fluxului de lucru în loc să schimbați acest selector partajat la jumătatea drumului.

Articole similare