Εναλλαγή διαδρομών proxy HTTP της Go χωρίς αλλαγή του Client.Transport
Χρησιμοποιήστε ένα συγχρονισμένο περιτύλιγμα RoundTripper για να δημοσιεύσετε έναν νέο διαμορφωμένο μεταφορέα proxy χωρίς να αλλάξετε ένα ενεργό πεδίο 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, πλήρως διαμορφωμένοι και ασφαλείς ως προς τον παραλληλισμό εκτελεστές μεταβάσεων. Κατασκευάστε κάθε μεταφορέα proxy πριν τον δημοσιεύσετε και αφήστε τη διαμόρφωσή του αμετάβλητη όσο τα αιτήματα τον χρησιμοποιούν.
Το κλείδωμα προστατεύει μόνο το στιγμιότυπο του δείκτη, οπότε ένα αργό αίτημα δεν κρατά το κλείδωμα δρομολόγησης σε όλη τη δικτυακή ανταλλαγή του. Ένα αίτημα που χρησιμοποιεί ήδη το προηγούμενο στιγμιότυπο συνεχίζει σε αυτόν τον μεταφορέα· η εναλλαγή δεν το επαναλαμβάνει ούτε μετακινεί τη σύνδεσή του.
Διατηρήστε και αποσύρετε τους παλιούς μεταφορείς μέσα στον περιορισμένο κύκλο ζωής της εφαρμογής, αφήνοντας την εργασία σε εξέλιξη να ολοκληρωθεί και κλείνοντας τις αδρανείς δεξαμενές όταν αρμόζει. Μια ανακατεύθυνση μπορεί να προκαλέσει άλλη RoundTrip μετά από εναλλαγή. Αν μια ολόκληρη ροή εργασίας απαιτεί μία διαδρομή, αναθέστε την στο όριο της ροής εργασίας αντί να αλλάζετε αυτόν τον κοινό επιλογέα στη μέση.