Wenn ein http.Client bereits von gleichzeitigen Anfragen geteilt wird, halten Sie sein Transport-Feld stabil. Ein Wrapper kann synchronisieren, welcher vollständig konfigurierte Transport jedem späteren Roundtrip zugeteilt wird:

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

Mit net/http und sync initialisieren Sie ihn, bevor der Client veröffentlicht wird:

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

slot.Set(nextTransport)

initialTransport und nextTransport müssen nicht-nil, vollständig konfigurierte und nebenläufigkeitssichere Roundtripper sein. Bauen Sie jeden Proxy-Transport, bevor Sie ihn veröffentlichen, und lassen Sie seine Konfiguration unverändert, solange Anfragen ihn nutzen.

Die Sperre schützt nur den Zeiger-Snapshot, sodass eine langsame Anfrage die Routing-Sperre nicht während ihres gesamten Netzwerkaustauschs hält. Eine Anfrage, die bereits den vorherigen Snapshot nutzt, läuft auf diesem Transport weiter; der Wechsel wiederholt sie nicht und verschiebt ihre Verbindung nicht.

Halten Sie alte Transporte über den begrenzten Lebenszyklus der Anwendung und mustern Sie sie aus, lassen Sie laufende Arbeit abschließen und schließen Sie im Leerlauf befindliche Pools, wenn es angebracht ist. Eine Weiterleitung kann nach einem Wechsel einen weiteren RoundTrip auslösen. Wenn ein ganzer Arbeitsablauf eine Route benötigt, weisen Sie sie an der Grenze des Arbeitsablaufs zu, statt diesen geteilten Selektor mittendrin zu ändern.

Ähnliche Artikel