Skip to content

Instantly share code, notes, and snippets.

@aparajita31pandey
Last active November 13, 2023 07:58
Show Gist options
  • Save aparajita31pandey/a3675733288ae286f8f6eff59bd92984 to your computer and use it in GitHub Desktop.
Save aparajita31pandey/a3675733288ae286f8f6eff59bd92984 to your computer and use it in GitHub Desktop.
Simple Load Balancer which uses RoundRobin algorithm to send requests into set of backends .
package main
import (
"fmt"
"io"
"net/http"
)
import "sync"
var (
backendServers = []string{
"http://localhost:8081/b8081",
"http://localhost:8082/b8082",
}
currentServer int
backendMutex sync.Mutex // To Study more around Mutex in Go
)
func main() {
var wg sync.WaitGroup
ports := []int{8081, 8082}
for _, port := range ports {
wg.Add(1)
go startBackEnd(port, wg)
}
http.HandleFunc("/", loadBalancerHandler)
fmt.Println("Load Balancer is listening on :8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
fmt.Printf("Error: %s\n", err)
}
}
/*
TO LEARN
1. sync.Mutex Working
2. Sprintf vs Printf vs Fprintf
3. More Around WaitGroup
*/
func startBackEnd(port int, wg sync.WaitGroup) {
defer wg.Done()
http.HandleFunc(fmt.Sprintf("/b%d", port),
func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Hello from backend server on :%d\n", port)
})
addr := fmt.Sprintf(":%d", port)
fmt.Printf("Backend is listening on: %d %s \n", port, addr)
err := http.ListenAndServe(addr, nil)
if err != nil {
fmt.Printf("Error for server on :%d; %s \n", port, err)
}
}
func getNextBackendServer() string {
backendMutex.Lock()
defer backendMutex.Unlock()
backend := backendServers[currentServer]
currentServer = (currentServer + 1) % len(backendServers)
return backend
}
func loadBalancerHandler(w http.ResponseWriter, r *http.Request) {
backend := getNextBackendServer()
resp, err := http.Get(backend)
if err != nil {
http.Error(w, "BackEnd Error", http.StatusInternalServerError)
}
defer resp.Body.Close()
// Copy the backend response headers and propagate them to the client
for key, values := range resp.Header {
for _, value := range values {
fmt.Println("VALUE", values)
w.Header().Set(key, value)
}
}
// Copy the backend response body and propagate it to the client
io.Copy(w, resp.Body)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment