Cambiare i percorsi proxy HTTP di Go senza modificare Client.Transport
Usa un wrapper RoundTripper sincronizzato per pubblicare un nuovo trasporto proxy configurato senza modificare un campo http.Client attivo.
Se un http.Client è già condiviso da richieste concorrenti, mantieni stabile il suo campo Transport. Un wrapper può sincronizzare quale trasporto completamente configurato riceve ogni successivo andata e ritorno:
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()
}Con net/http e sync, inizializzalo prima di pubblicare il client:
slot := &routeSlot{current: initialTransport}
client := &http.Client{Transport: slot}
slot.Set(nextTransport)initialTransport e nextTransport devono essere esecutori di andata e ritorno non nil, completamente configurati e sicuri rispetto alla concorrenza. Costruisci ogni trasporto proxy prima di pubblicarlo e lascia invariata la sua configurazione mentre le richieste lo usano.
Il lock protegge solo l'istantanea del puntatore, quindi una richiesta lenta non trattiene il lock di instradamento per tutto il suo scambio di rete. Una richiesta che usa già l'istantanea precedente continua su quel trasporto; il cambio non la ripete né sposta la sua connessione.
Conserva e dismetti i vecchi trasporti lungo il ciclo di vita limitato dell'applicazione, lasciando che il lavoro in corso termini e chiudendo i pool inattivi quando opportuno. Un reindirizzamento può causare un altro RoundTrip dopo un cambio. Se un intero flusso di lavoro richiede un solo percorso, assegnalo al confine del flusso di lavoro invece di cambiare questo selettore condiviso a metà strada.