تغییر مسیرهای پراکسی HTTP در Go بدون تغییر Client.Transport
برای انتشار یک ترنسپورت پراکسی تازه پیکربندیشده بدون تغییر فیلد فعال http.Client از یک پوشش RoundTripper همگامشده استفاده کنید.
اگر 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 باید غیر nil، کاملاً پیکربندیشده و از نظر همزمانی ایمن باشند. هر ترنسپورت پراکسی را پیش از انتشارش بسازید و پیکربندی آن را تا زمانی که درخواستها از آن استفاده میکنند تغییر ندهید.
قفل تنها از عکس لحظهای اشارهگر محافظت میکند، بنابراین یک درخواست کند قفل مسیریابی را در تمام مدت تبادل شبکهای خود نگه نمیدارد. درخواستی که از عکس قبلی استفاده میکند روی همان ترنسپورت ادامه میدهد؛ تغییر آن را دوباره اجرا نمیکند و اتصالش را جابهجا نمیکند.
ترنسپورتهای قدیمی را در چرخه عمر محدود برنامه نگه دارید و بازنشسته کنید، بگذارید کار در جریان تمام شود و در صورت لزوم استخرهای بیکار را ببندید. یک تغییر مسیر میتواند پس از تعویض باعث RoundTrip دیگری شود. اگر یک گردش کار کامل به یک مسیر نیاز دارد، آن مسیر را در مرز گردش کار تعیین کنید، نه اینکه این انتخابگر مشترک را در میانه راه تغییر دهید.