Skip to content

Commit

Permalink
feat : lc handler
Browse files Browse the repository at this point in the history
  • Loading branch information
seipan committed Oct 2, 2023
1 parent 201bd5f commit 312f67b
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 88 deletions.
40 changes: 40 additions & 0 deletions backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,43 @@ func (backend *Backend) GetIsDead() bool {
func (backend *Backend) GetConnections() int {
return backend.connections
}

func NewBackend(url string) Backend {
return Backend{
URL: url,
IsDead: false,
}
}

func NewDefaultBackend() []Backend {
return []Backend{
{
URL: "http://localhost:8081/",
IsDead: false,
},
{
URL: "http://localhost:8082/",
IsDead: false,
},
{
URL: "http://localhost:8083/",
IsDead: false,
},
{
URL: "http://localhost:8086/",
IsDead: false,
},
{
URL: "http://localhost:8087/",
IsDead: false,
},
{
URL: "http://localhost:8088/",
IsDead: false,
},
{
URL: "http://localhost:8089/",
IsDead: false,
},
}
}
31 changes: 0 additions & 31 deletions config.json

This file was deleted.

38 changes: 38 additions & 0 deletions lc/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package lc

import (
"log"
"net/http"
"net/http/httputil"
"net/url"

"github.com/seipan/mylb/backend"
)

// lbHandler is a handler for loadbalancing
func LcHandler(w http.ResponseWriter, r *http.Request) {
idx := 0
bcds := backend.NewDefaultBackend()
lc := NewlcserverPool(bcds)
maxLen := len(bcds)
// Round Robin
lc.mu.Lock()
currentBackend := lc.Backends[idx%maxLen]
if currentBackend.GetIsDead() {
idx++
}
targetURL, err := url.Parse(lc.Backends[idx%maxLen].URL)
if err != nil {
log.Fatal(err.Error())
}
idx++
lc.mu.Unlock()
reverseProxy := httputil.NewSingleHostReverseProxy(targetURL)
reverseProxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, e error) {
// NOTE: It is better to implement retry.
log.Printf("%v is dead.", targetURL)
currentBackend.SetDead(true)
LcHandler(w, r)
}
reverseProxy.ServeHTTP(w, r)
}
11 changes: 9 additions & 2 deletions lc/serverpool.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package lc

import (
"sync"

"github.com/seipan/mylb/backend"
"github.com/seipan/mylb/proxy"
)

type lcserverPool struct {
Proxy proxy.Proxy `json:"proxy"`
Backends []backend.Backend `json:"backends"`
mu sync.RWMutex
}

func (s *lcserverPool) GetNextValidPeer() backend.Backend {
Expand All @@ -29,3 +30,9 @@ func (s *lcserverPool) GetNextValidPeer() backend.Backend {
}
return leastConnectedPeer
}

func NewlcserverPool(backends []backend.Backend) lcserverPool {
return lcserverPool{
Backends: backends,
}
}
54 changes: 4 additions & 50 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,67 +2,21 @@ package main

import (
"context"
"encoding/json"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"sync"

"github.com/seipan/mylb/backend"
"github.com/seipan/mylb/proxy"
"github.com/seipan/mylb/lc"
)

type Config struct {
Proxy proxy.Proxy `json:"proxy"`
Backends []backend.Backend `json:"backends"`
}

var cfg Config
var mu sync.Mutex
var idx int = 0

// lbHandler is a handler for loadbalancing
func lbHandler(w http.ResponseWriter, r *http.Request) {
maxLen := len(cfg.Backends)
// Round Robin
mu.Lock()
currentBackend := cfg.Backends[idx%maxLen]
if currentBackend.GetIsDead() {
idx++
}
targetURL, err := url.Parse(cfg.Backends[idx%maxLen].URL)
if err != nil {
log.Fatal(err.Error())
}
idx++
mu.Unlock()
reverseProxy := httputil.NewSingleHostReverseProxy(targetURL)
reverseProxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, e error) {
// NOTE: It is better to implement retry.
log.Printf("%v is dead.", targetURL)
currentBackend.SetDead(true)
lbHandler(w, r)
}
reverseProxy.ServeHTTP(w, r)
}

// Serve serves a loadbalancer.
func main() {
data, err := os.ReadFile("./config.json")
if err != nil {
log.Fatal(err.Error())
}
json.Unmarshal(data, &cfg)

go healthCheck(context.Background(), nil)

s := http.Server{
Addr: ":" + cfg.Proxy.Port,
Handler: http.HandlerFunc(lbHandler),
Addr: ":" + "8080",
Handler: http.HandlerFunc(lc.LcHandler),
}
if err = s.ListenAndServe(); err != nil {
if err := s.ListenAndServe(); err != nil {
log.Fatal(err.Error())
}
}
5 changes: 0 additions & 5 deletions proxy/proxy.go

This file was deleted.

0 comments on commit 312f67b

Please sign in to comment.