Ein gemeinsamer Round-Robin-Proxy-Selektor in Go
Halte einen Go-Proxy-Selektor über Requests hinweg am Leben, schütze den gemeinsamen Auswahlzustand und unterscheide das Wählen einer Route vom Beobachten ihres Ausgangs.
Ein Selektor kann sich perfekt abwechseln und trotzdem immer den ersten Proxy wählen. Der Fehler besteht darin, versehentlich für jede Anfrage einen neuen Selektor anzulegen, der seinen Zähler zurücksetzt, bevor er eine zweite Wahl treffen kann.
Erzeuge den Selektor einmal und halte ihn zusammen mit dem Transport fest. Die HTTP-Proxy-Liste kann öffentliche HTTP-Kandidaten für die URL-Menge liefern, wenn die Anfragen öffentliche Zwischenstellen zulassen. Beginne mit einer bereits geprüften, nicht leeren Liste von Proxy-URLs:
func rotatingProxy(urls []*url.URL) func(*http.Request) (*url.URL, error) {
var mu sync.Mutex
next := 0
return func(*http.Request) (*url.URL, error) {
mu.Lock()
selected := urls[next]
next = (next + 1) % len(urls)
mu.Unlock()
return selected, nil
}
}
Die umgebende Anwendung muss eine leere Liste ablehnen, die URLs prüfen und die normalen Importe net/http, net/url und sync verwenden. Die Liste sollte unveränderlich bleiben, solange dieser Selektor sie nutzt, oder über ein separat synchronisiertes Design ersetzt werden.
Hänge die zurückgegebene Funktion an einen fest gehaltenen http.Transport. Der Mutex schützt die Auswahlreihenfolge über gleichzeitige Rückrufe hinweg. Er verlangt nicht, dass während einer langsamen Netzwerkanfrage eine Sperre gehalten wird.
Verbrauche eine Route nicht nur, um sie auszugeben
Ein erneuter Aufruf des Selektors für eine Diagnosemeldung erhöht den Zähler erneut. Diese Ausgabe beschreibt dann vielleicht den nächsten Kandidaten statt den Kandidaten, den die untersuchte Anfrage genutzt hat. Erfasse die Auswahl innerhalb des echten Rückrufs mit einer sicheren Endpunktkennung.
Ein Rückrufaufruf ist kein Beweis für eine erfolgreich zugestellte Anfrage. Weiterleitungen oder zusätzliche Transportversuche können die einfache Annahme „ein Anwendungsaufruf, eine Auswahl“ verkomplizieren. Wenn ein Workflow eine Route über mehrere Vorgänge hinweg beibehalten muss, wähle diese Route an der Grenze des Workflows, statt einen globalen rotierenden Rückruf zu verwenden.
Round-Robin verspricht außerdem keine unterschiedlichen öffentlichen Ausgänge. Es plant Endpunkte ein. Die endgültige Identität bleibt eine Eigenschaft des Pfades, den jeder Endpunkt bereitstellt.