Skip to content

Commit

Permalink
feat: improve code
Browse files Browse the repository at this point in the history
  • Loading branch information
dhyanio committed Oct 30, 2024
1 parent c15e974 commit a8a3770
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 23 deletions.
15 changes: 15 additions & 0 deletions example/simple.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

import (
"github.com/dhyanio/golb"
)

func main() {
serverList := []string{
"https://www.google.com/",
"https://github.com/dhyanio",
"https://www.linkedin.com/in/dhyanio/",
}

golb.Start(serverList, "3000")
}
39 changes: 24 additions & 15 deletions loadbalancer.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
package golb

import (
"fmt"
"log"
"net/http"
"sync"
)

// LoadBalancer represents a simple round-robin load balancer.
type LoadBalancer struct {
port string
roundRobinCount int
servers []Server
mu sync.Mutex
}

// NewLoadBalancer initializes a LoadBalancer with the specified port and servers.
func NewLoadBalancer(port string, servers []Server) *LoadBalancer {
return &LoadBalancer{
port: port,
roundRobinCount: 0,
servers: servers,
}
}

// getNextAvailableServer returns the next available server in a round-robin fashion.
func (lb *LoadBalancer) getNextAvailableServer() Server {
lb.mu.Lock()
defer lb.mu.Unlock()

server := lb.servers[lb.roundRobinCount%len(lb.servers)]
for !server.IsAlive() {
lb.roundRobinCount++
Expand All @@ -28,26 +37,26 @@ func (lb *LoadBalancer) getNextAvailableServer() Server {
return server
}

func (lb *LoadBalancer) serverProxy(rw http.ResponseWriter, r *http.Request) {
targetSever := lb.getNextAvailableServer()
fmt.Printf("Forwarding request to address %q\n", targetSever.Address())
targetSever.Serve(rw, r)
// serveProxy forwards the request to the selected server.
func (lb *LoadBalancer) serveProxy(rw http.ResponseWriter, r *http.Request) {
targetServer := lb.getNextAvailableServer()
log.Printf("Forwarding request to address %q\n", targetServer.Address())
targetServer.Serve(rw, r)
}

// Start starts loadbalancer
func start(serverAdd []string, port string) {
// Start initializes servers, sets up the load balancer, and starts listening on the specified port.
func Start(serverAddresses []string, port string) {
var servers []Server

for _, value := range serverAdd {
servers = append(servers, newSimpleServer(value))
for _, addr := range serverAddresses {
servers = append(servers, NewSimpleServer(addr))
}

lb := NewLoadBalancer(port, servers)
handleRedirect := func(rw http.ResponseWriter, req *http.Request) {
lb.serverProxy(rw, req)
}
http.HandleFunc("/", lb.serveProxy)

http.HandleFunc("/", handleRedirect)
fmt.Printf("Serving requests at localhost:%s\n", lb.port)
http.ListenAndServe(":"+lb.port, nil)
log.Printf("Load balancer listening on port %s\n", port)
if err := http.ListenAndServe(":"+port, nil); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
}
25 changes: 17 additions & 8 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,41 @@ import (
"net/url"
)

// Server represents server
// Server represents a load-balanced server interface.
type Server interface {
Address() string
IsAlive() bool
Serve(rw http.ResponseWriter, r *http.Request)
Serve(http.ResponseWriter, *http.Request)
}

type simpleServer struct {
// SimpleServer represents a basic HTTP server with reverse proxy capabilities.
type SimpleServer struct {
addr string
proxy *httputil.ReverseProxy
}

func newSimpleServer(addr string) *simpleServer {
// NewSimpleServer creates a new instance of SimpleServer with a reverse proxy.
func NewSimpleServer(addr string) *SimpleServer {
serverUrl, err := url.Parse(addr)
handleErr(err)

return &simpleServer{
return &SimpleServer{
addr: addr,
proxy: httputil.NewSingleHostReverseProxy(serverUrl),
}
}

func (s *simpleServer) Address() string { return s.addr }
// Address returns the server address.
func (s *SimpleServer) Address() string {
return s.addr
}

func (s *simpleServer) IsAlive() bool { return true }
// IsAlive always returns true, but this could be expanded for real health checks.
func (s *SimpleServer) IsAlive() bool {
return true
}

func (s *simpleServer) Serve(rw http.ResponseWriter, req *http.Request) {
// Serve handles the HTTP request by forwarding it to the reverse proxy.
func (s *SimpleServer) Serve(rw http.ResponseWriter, req *http.Request) {
s.proxy.ServeHTTP(rw, req)
}

0 comments on commit a8a3770

Please sign in to comment.