Go における共有ラウンドロビン・プロキシセレクタ
Go のプロキシセレクタをリクエスト間で生かし続け、共有の選択状態を保護し、ルートの選択とその出口の観察を区別します。
セレクタは完璧に順番を回していても、最初のプロキシを選び続けることがあります。原因は、リクエストごとに誤って新しいセレクタを作ってしまい、2 番目の選択肢を持つ前にカウンタがリセットされることです。
セレクタは一度だけ構築し、トランスポートと一緒に保持します。HTTP プロキシ一覧は、リクエストが公的な中間業者を許す場合に、URL 集合向けの公開 HTTP 候補を提供できます。あらかじめ検証済みで空でないプロキシ URL の一覧から始めてください。
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
}
}
周囲のアプリケーションは空の一覧を拒否し、URL を検証し、通常の net/http、net/url、sync のインポートを使う必要があります。一覧はこのセレクタが使っている間は不変のままにするか、別途同期化された設計で置き換えるべきです。
返された関数を、保持した 1 つの http.Transport に取り付けます。ミューテックスは同時に走るコールバック間で選択順序を保護します。遅いネットワーク要求が完了する間ロックを保持する必要はありません。
表示するためだけにルートを消費しない
診断メッセージのためにセレクタを再度呼ぶと、カウンタがまた進みます。その出力は、調査中のリクエストが使った候補ではなく次の候補を表すかもしれません。実際のコールバックの中で、安全なエンドポイント識別子を使って選択を記録してください。
コールバックの呼び出しは、要求が正常に配信された証拠ではありません。リダイレクトや追加のトランスポート試行は「アプリケーション呼び出し 1 回、選択 1 回」という単純な前提を複雑にします。ワークフローが複数の操作を通して 1 つのルートを保つ必要があるなら、グローバルに回転するコールバックを使う代わりに ワークフローの境界でそのルートを選んでください。
ラウンドロビンも、異なる公開出口を約束するものではありません。それはエンドポイントを順番に割り当てるだけです。最終的な同一性は、各エンドポイントが提供する経路の性質のままです。