不提供 http 服务时的 golang 客户端负载均衡器

作为一个golang n00b,我有一个 go 程序,它将消息读入 kafka,修改它们,然后将它们发布到列表中的一个 http 端点。

到目前为止,我们用随机数做了一些非常基本的循环

cur := rand.Int() % len(httpEndpointList)

我想改进它并根据端点的响应时间或类似的东西增加端点的权重。

我查看了库,但我似乎发现的所有内容都是为使用 http.Handle 用作中间件而编写的。

我的情况是,我不为每个人提供 http 请求。

任何想法我怎么能在我的 golang 程序中完成那种更高级的客户端负载平衡?

我想避免在我的环境中使用另一个 haproxy 或类似的。



慕森王
浏览 100回答 1
1回答

偶然的你

有一个非常简单的加权随机选择算法:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "math/rand")type Endpoint struct {&nbsp; &nbsp; URL&nbsp; &nbsp; string&nbsp; &nbsp; Weight int}func RandomWeightedSelector(endpoints []Endpoint) Endpoint {&nbsp; &nbsp; // this first loop should be optimised so it only gets computed once&nbsp; &nbsp; max := 0&nbsp; &nbsp; for _, endpoint := range endpoints {&nbsp; &nbsp; &nbsp; &nbsp; max = max + endpoint.Weight&nbsp; &nbsp; }&nbsp; &nbsp; r := rand.Intn(max)&nbsp; &nbsp; for _, endpoint := range endpoints {&nbsp; &nbsp; &nbsp; &nbsp; if r < endpoint.Weight {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return endpoint&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r = r - endpoint.Weight&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; // should never get to this point because r is smaller than max&nbsp; &nbsp; return Endpoint{}}func main() {&nbsp; &nbsp; endpoints := []Endpoint{&nbsp; &nbsp; &nbsp; &nbsp; {Weight: 1, URL: "https://web1.example.com"},&nbsp; &nbsp; &nbsp; &nbsp; {Weight: 2, URL: "https://web2.example.com"},&nbsp; &nbsp; }&nbsp; &nbsp; count1 := 0&nbsp; &nbsp; count2 := 0&nbsp; &nbsp; for i := 0; i < 100; i++ {&nbsp; &nbsp; &nbsp; &nbsp; switch RandomWeightedSelector(endpoints).URL {&nbsp; &nbsp; &nbsp; &nbsp; case "https://web1.example.com":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; count1++&nbsp; &nbsp; &nbsp; &nbsp; case "https://web2.example.com":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; count2++&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println("Times web1: ", count1)&nbsp; &nbsp; fmt.Println("Times web2: ", count2)}在可以优化的情况下,这是最幼稚的。当然对于生产你不应该每次都计算最大值,但除此之外,这基本上是解决方案。这是一个更专业和面向对象的版本,不会每次都重新计算最大值:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "math/rand")type Endpoint struct {&nbsp; &nbsp; URL&nbsp; &nbsp; string&nbsp; &nbsp; Weight int}type RandomWeightedSelector struct {&nbsp; &nbsp; max&nbsp; &nbsp; &nbsp; &nbsp;int&nbsp; &nbsp; endpoints []Endpoint}func (rws *RandomWeightedSelector) AddEndpoint(endpoint Endpoint) {&nbsp; &nbsp; rws.endpoints = append(rws.endpoints, endpoint)&nbsp; &nbsp; rws.max += endpoint.Weight}func (rws *RandomWeightedSelector) Select() Endpoint {&nbsp; &nbsp; r := rand.Intn(rws.max)&nbsp; &nbsp; for _, endpoint := range rws.endpoints {&nbsp; &nbsp; &nbsp; &nbsp; if r < endpoint.Weight {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return endpoint&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r = r - endpoint.Weight&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; // should never get to this point because r is smaller than max&nbsp; &nbsp; return Endpoint{}}func main() {&nbsp; &nbsp; var rws RandomWeightedSelector&nbsp; &nbsp; rws.AddEndpoint(Endpoint{Weight: 1, URL: "https://web1.example.com"})&nbsp; &nbsp; rws.AddEndpoint(Endpoint{Weight: 2, URL: "https://web2.example.com"})&nbsp; &nbsp; count1 := 0&nbsp; &nbsp; count2 := 0&nbsp; &nbsp; for i := 0; i < 100; i++ {&nbsp; &nbsp; &nbsp; &nbsp; switch rws.Select().URL {&nbsp; &nbsp; &nbsp; &nbsp; case "https://web1.example.com":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; count1++&nbsp; &nbsp; &nbsp; &nbsp; case "https://web2.example.com":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; count2++&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println("Times web1: ", count1)&nbsp; &nbsp; fmt.Println("Times web2: ", count2)}对于基于端点延迟等指标更新权重的部分,我将创建一个不同的对象,该对象使用此指标来更新 RandomWeightedSelector 对象中的权重。我认为一起实施它会违反单一责任。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go