作为 golang n00b ,我有一个go程序,可以将消息读入kafka,进行修改,然后将其发布到列表中的http端点之一。
截至目前,我们已经进行了一些非常基本的随机轮循
cur := rand.Int() % len(httpEndpointList)
我想改善这一点,并根据端点的响应时间或类似的方法来增加端点的权重。
我已经研究了库,但是似乎所有使用http.Handle编写的代码都用作中间件。例如,请参见oxy lib roundrobin
我的情况下,我不说每个HTTP请求。
有什么想法可以在我的golang程序中实现更高级的客户端负载平衡吗?
我想避免在我的环境中使用另一种灭螺灵或类似药物。
答案 0 :(得分:0)
有一个非常简单的加权随机选择算法:
package main
import (
"fmt"
"math/rand"
)
type Endpoint struct {
URL string
Weight int
}
func RandomWeightedSelector(endpoints []Endpoint) Endpoint {
// this first loop should be optimised so it only gets computed once
max := 0
for _, endpoint := range endpoints {
max = max + endpoint.Weight
}
r := rand.Intn(max)
for _, endpoint := range endpoints {
if r < endpoint.Weight {
return endpoint
} else {
r = r - endpoint.Weight
}
}
// should never get to this point because r is smaller than max
return Endpoint{}
}
func main() {
endpoints := []Endpoint{
{Weight: 1, URL: "https://web1.example.com"},
{Weight: 2, URL: "https://web2.example.com"},
}
count1 := 0
count2 := 0
for i := 0; i < 100; i++ {
switch RandomWeightedSelector(endpoints).URL {
case "https://web1.example.com":
count1++
case "https://web2.example.com":
count2++
}
}
fmt.Println("Times web1: ", count1)
fmt.Println("Times web2: ", count2)
}
在可以优化的情况下,这是最幼稚的。绝对对于生产而言,您不必每次都计算最大值,但除此之外,这基本上是解决方案。
这里有一个更专业的OO版本,它不会每次都重新计算max:
package main
import (
"fmt"
"math/rand"
)
type Endpoint struct {
URL string
Weight int
}
type RandomWeightedSelector struct {
max int
endpoints []Endpoint
}
func (rws *RandomWeightedSelector) AddEndpoint(endpoint Endpoint) {
rws.endpoints = append(rws.endpoints, endpoint)
rws.max += endpoint.Weight
}
func (rws *RandomWeightedSelector) Select() Endpoint {
r := rand.Intn(rws.max)
for _, endpoint := range rws.endpoints {
if r < endpoint.Weight {
return endpoint
} else {
r = r - endpoint.Weight
}
}
// should never get to this point because r is smaller than max
return Endpoint{}
}
func main() {
var rws RandomWeightedSelector
rws.AddEndpoint(Endpoint{Weight: 1, URL: "https://web1.example.com"})
rws.AddEndpoint(Endpoint{Weight: 2, URL: "https://web2.example.com"})
count1 := 0
count2 := 0
for i := 0; i < 100; i++ {
switch rws.Select().URL {
case "https://web1.example.com":
count1++
case "https://web2.example.com":
count2++
}
}
fmt.Println("Times web1: ", count1)
fmt.Println("Times web2: ", count2)
}
对于基于诸如端点等待时间之类的度量来更新权重的部分,我将创建一个不同的对象,该对象使用该度量来更新RandomWeightedSelector对象中的权重。我认为,将其全部实施将有悖于单一责任。