社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
负载均衡有不同的负载策略
Round Robin:轮询,就是每个请求依次打到每个服务商去
Weighted Round Robin :加权轮询,额外加了权重
Least Connections :最少连接,优先请求到连接数最少的服务器上去
补充的其它策略参考 https://blog.csdn.net/qq_28119741/article/details/102333133
我们这次实现的负载均衡,使用三者上面最简单的一个,轮询
轮询是简单的,它给了每个后端相等的机会,接受请求或者任务
如上图所示,循环接受转发的请求,任务,但是,我们不能直接用这个不是吗?
如果一个backend不可用了怎么办,我们可能不想再分配给它,所以我们需要只分配给运行正常的backend
在改正这个方案后,现在我们知道我们想要一个方法知道一个 backend的全部详细的信息,我们需要跟踪这个backend是alive or dead 同时也要保持跟踪的这个url
所以我们简单的定义了一个结构体hold我们的后端
type Backend struct {
URL *url.URL
Alive bool
mux sync.RWMutex
ReverseProxy *httputil.ReverseProxy
}
不要担心,后面我会解释这些字段的含义
现在我们需要一个方式跟踪全部的后端在我们的复制均衡里面,对于这个我们可以简单的使用一个slice和一个计数变量。我们定义了如下的结构体
type ServerPool struct {
backends []*Backend
current uint64
}
正如我们已经说明的,负载均衡的目标是要把流量分配到不同的后端,然后返回结果给客户端。
go的文档是这样说明reverseproxy的
ReverseProxy is an HTTP Handler that takes an incoming request and sends it to another server, proxying the response back to the client.
反向代理是一个接受一个请求,然后转发给另一个服务,并代理这个响应返回给客户端 的一个http handler
反向代理的说明可以参考 https://blog.csdn.net/qq_28119741/article/details/94648300
这正是我们想要的,不需要重复造轮子。我们可以简单的转发我们的原始请求通过这个反向代理
u, _ := url.Parse("http://localhost:8080")
rp := httputil.NewSingleHostReverseProxy(u)
// initialize your server and add this as handler
http.HandlerFunc(rp.ServeHTTP)
使用 httputil.NewSingleHostReverseProxy(url) 我们初始化了一个反向代理可以转发请求沿着这个url
在上面的例子中,全部的请求被传递到 localhost:8080,同时结果被发送给客户端
在下一次的转发前,我们需要摘掉挂掉的后端,但是做任何事之前我们需要一个计数的方法
下面的代码用来计算下一个请求轮询到的后端的索引
func (s *ServerPool) NextIndex() int {
return int(atomic.AddUint64(&s.current, uint64(1)) % uint64(len(s.backends)))
}
这里使用原子变量,就不需要锁来消耗资源了
这里我们将要处理挂掉的后端
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!