สลับเส้นทางพร็อกซี HTTP ของ Go โดยไม่แก้ไข Client.Transport
ใช้ตัวห่อ RoundTripper ที่ซิงโครไนซ์เพื่อเผยแพร่ทรานสปอร์ตพร็อกซีที่กำหนดค่าใหม่ โดยไม่แก้ไขฟิลด์ http.Client ที่กำลังทำงาน
หาก 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 อีกครั้งหลังการสลับ หากทั้งเวิร์กโฟลว์ต้องใช้เส้นทางเดียว ให้กำหนดเส้นทางนั้นที่ขอบเขตของเวิร์กโฟลว์ แทนการเปลี่ยนตัวเลือกที่แชร์นี้กลางคัน