http.Client가 이미 동시 요청에 공유되고 있다면 Transport 필드를 안정적으로 유지하세요. 래퍼는 이후 각 왕복이 어떤 완전히 구성된 전송체를 받을지 동기화할 수 있습니다:

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

net/http와 sync를 사용해 클라이언트를 게시하기 전에 초기화하세요:

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

slot.Set(nextTransport)

initialTransport와 nextTransport는 non-nil이어야 하고, 완전히 구성되어야 하며, 동시성에 안전해야 합니다. 각 프록시 전송체는 게시 전에 만들고, 요청이 사용하는 동안에는 그 구성을 바꾸지 마세요.

잠금은 포인터 스냅숏만 보호하므로 느린 요청이 전체 네트워크 교환 동안 라우팅 잠금을 붙잡지 않습니다. 이전 스냅숏을 사용하는 요청은 그 전송체에서 계속 진행합니다. 전환은 그 요청을 다시 실행하지 않고 연결을 옮기지도 않습니다.

오래된 전송체는 애플리케이션의 제한된 수명 주기 안에서 유지하고 폐기하며, 진행 중인 작업이 끝나도록 하고 필요할 때 유휴 풀을 닫으세요. 리디렉션은 전환 후 또 다른 RoundTrip을 일으킬 수 있습니다. 워크플로 전체가 하나의 경로를 필요로 한다면, 이 공유 선택기를 중간에 바꾸지 말고 워크플로 경계에서 그 경로를 지정하세요.

관련 글