Nếu một http.Client đã được các yêu cầu đồng thời chia sẻ, hãy giữ trường Transport của nó ổn định. Lớp bọc có thể đồng bộ transport nào đã được cấu hình đầy đủ sẽ nhận mỗi vòng tiếp theo:

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

Với net/http và sync, hãy khởi tạo nó trước khi công bố client:

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

slot.Set(nextTransport)

initialTransport và nextTransport phải khác nil, được cấu hình đầy đủ và an toàn với việc chạy đồng thời. Hãy dựng mỗi transport proxy trước khi công bố nó, và để nguyên cấu hình của nó trong khi các yêu cầu đang dùng.

Khóa chỉ bảo vệ ảnh chụp con trỏ, nên một yêu cầu chậm không giữ khóa định tuyến suốt quá trình trao đổi mạng của nó. Một yêu cầu đã dùng ảnh chụp trước đó tiếp tục trên transport ấy; việc chuyển không chạy lại nó hay di chuyển kết nối của nó.

Hãy giữ và loại bỏ các transport cũ theo vòng đời có giới hạn của ứng dụng, cho phép công việc đang chạy hoàn tất và đóng các pool nhàn rỗi khi thích hợp. Một chuyển hướng có thể gây ra một RoundTrip khác sau khi chuyển. Nếu cả một quy trình làm việc cần một tuyến, hãy gán tuyến đó tại ranh giới quy trình làm việc thay vì đổi bộ chọn dùng chung này giữa chừng.

Bài viết liên quan