fix: use weighted random pick for load balancing instead of sequential iteration
This commit is contained in:
@@ -163,11 +163,29 @@ func upstreamURL(ch *store.Channel, proto, path string) string {
|
||||
return ch.UpstreamURL(proto, path)
|
||||
}
|
||||
|
||||
// doProxy 通用代理(M5):遍历候选渠道,按需转换;可安全重试的失败自动故障转移。
|
||||
// doProxy 通用代理(M5):加权随机选一个候选渠道;失败自动故障转移。
|
||||
func (g *Gateway) doProxy(c *gin.Context, cands []channel.Candidate, clientProto string, body []byte, stream bool, sink *usageSink) {
|
||||
if len(cands) == 0 {
|
||||
apiError(c, http.StatusBadGateway, "upstream_error", "no available channel")
|
||||
g.recordError(c, nil, nil, now(), "no_available_channel")
|
||||
return
|
||||
}
|
||||
// 加权随机选择起始渠道
|
||||
picked := g.ch.Pick(cands)
|
||||
startIdx := 0
|
||||
for i, cand := range cands {
|
||||
if cand.Channel.ID == picked.ID {
|
||||
startIdx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var lastStatus = http.StatusBadGateway
|
||||
var lastBody = []byte("all upstream channels failed")
|
||||
for _, cand := range cands {
|
||||
// 从选中的渠道开始遍历,到末尾后再从头遍历到选中渠道之前
|
||||
for offset := 0; offset < len(cands); offset++ {
|
||||
idx := (startIdx + offset) % len(cands)
|
||||
cand := cands[idx]
|
||||
ch := cand.Channel
|
||||
plan, err := prepareUpstream(ch, clientProto, body, cand.UpstreamModel)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user