Pokud je http.Client již sdílen souběžnými požadavky, udržujte jeho pole Transport stabilní. Obal dokáže synchronizovat, který plně nakonfigurovaný transport dostane každé další kolo:

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()
}

Pomocí net/http a sync jej inicializujte před publikováním klienta:

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

slot.Set(nextTransport)

initialTransport a nextTransport musí být non-nil, plně nakonfigurované a vůči souběžnosti bezpečné prováděče kol. Každý proxy transport sestavte před jeho publikováním a jeho konfiguraci neměňte, dokud jej požadavky používají.

Zámek chrání jen snímek ukazatele, takže pomalý požadavek nedrží směrovací zámek po celou dobu síťové výměny. Požadavek, který už používá předchozí snímek, pokračuje na tomto transportu; přepnutí jej nespouští znovu ani nepřesouvá jeho spojení.

Staré transporty uchovávejte a vyřazujte v rámci omezeného životního cyklu aplikace, nechte běžící práci dokončit a podle potřeby zavřete nečinné fondy. Přesměrování může po přepnutí vyvolat další RoundTrip. Pokud celý pracovní postup vyžaduje jednu trasu, přiřaďte ji na hranici pracovního postupu, místo abyste tento sdílený selektor měnili v jeho průběhu.

Související články