В данном случае используется довольно простой алгоритм Round-Robin.
Начнем с базового объекта server, который содержит 3 атрибута, связанных с сервером
• Address()
• IsAlive()
• Функция Serve() для работы с запросами
type Server interface {
Address() string
IsAlive() bool
Serve(rw http.ResponseWriter, req *http.Request)
}
В дальнейшем используется второй тип объекта – simpleServer.
type simpleServer struct {
addr string
proxy *httputil.ReverseProxy
}
После определения методов, используемых в указанных объектах, мы создаем loadbalancer вместе с функцией getNextAvailableServer().
func NewLoadBalancer(port string, servers []Server) *LoadBalancer {
return &LoadBalancer{
port: port,
roundRobinCount: 0,
servers: servers,
}
}
func (lb *LoadBalancer) getNextAvailableServer() Server {
server := lb.servers[lb.roundRobinCount%len(lb.servers)]
for !server.IsAlive() {
lb.roundRobinCount++
server = lb.servers[lb.roundRobinCount%len(lb.servers)]
}
lb.roundRobinCount++
return server
}
Вызываем main()
func main() {
servers := []Server{
newSimpleServer("https://snapcraft.io"),
newSimpleServer("https://github.com/sambhavsaxena"),
newSimpleServer("http://localhost:3001"),
}
lb := NewLoadBalancer("3000", servers)
handleRedirect := func(rw http.ResponseWriter, req *http.Request) {
lb.serveProxy(rw, req)
}
http.HandleFunc("/", handleRedirect)
fmt.Printf("distributing requests fired at 'localhost:%s'\n", lb.port)
http.ListenAndServe(":"+lb.port, nil)
}
▪Статья
▪Полный код
@golang_interview