Jeśli http.Client jest już współdzielony przez równoległe żądania, utrzymuj jego pole Transport stabilne. Otoczka może synchronizować, który w pełni skonfigurowany transport otrzyma każdy kolejny obieg:

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

Za pomocą net/http i sync zainicjuj go przed opublikowaniem klienta:

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

slot.Set(nextTransport)

initialTransport i nextTransport muszą być nie-nil, w pełni skonfigurowane i bezpieczne pod względem współbieżności. Buduj każdy transport proxy przed jego opublikowaniem i nie zmieniaj jego konfiguracji, dopóki żądania go używają.

Blokada chroni tylko migawkę wskaźnika, więc wolne żądanie nie trzyma blokady routingu przez całą wymianę sieciową. Żądanie, które już używa poprzedniej migawki, kontynuuje na tym transporcie; przełączenie nie odtwarza go ponownie ani nie przenosi jego połączenia.

Zachowuj i wycofuj stare transporty w ograniczonym cyklu życia aplikacji, pozwalając zakończyć pracę w toku i zamykając bezczynne pule, gdy to właściwe. Przekierowanie może po przełączeniu wywołać kolejny RoundTrip. Jeśli cały przepływ pracy wymaga jednej trasy, przypisz ją na granicy przepływu pracy, zamiast zmieniać ten współdzielony selektor w połowie drogi.

Powiązane artykuły